first draft of gms authentication

This commit is contained in:
Claus-Peter Huebner 2024-03-15 01:16:33 +01:00
parent 185275ad53
commit 2b8b086f6c
8 changed files with 108 additions and 1 deletions

View File

@ -144,3 +144,44 @@ export async function createGmsUser(apiKey: string, user: GmsUser): Promise<bool
throw new LogError(error.message)
}
}
export async function verifyAuthToken(
// apiKey: string,
communityUuid: string,
token: string,
): Promise<string> {
const baseUrl = CONFIG.GMS_URL.endsWith('/') ? CONFIG.GMS_URL : CONFIG.GMS_URL.concat('/')
const service = 'verify-auth-token'
const config = {
headers: {
accept: 'application/json',
language: 'en',
timezone: 'UTC',
connection: 'keep-alive',
// authorization: apiKey,
},
}
const data = {
uuid: communityUuid,
token: token,
}
try {
const result = await axios.get(baseUrl.concat(service), data, config)
logger.debug('GET-Response of verify-auth-token:', result)
if (result.status !== 200) {
throw new LogError(
'HTTP Status Error in verify-auth-token:',
result.status,
result.statusText,
)
}
logger.debug('responseData:', result.data.responseData)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const playgroundUri: string = JSON.parse(result.data.responseData.data)
logger.debug('verifyAuthToken=', playgroundUri)
return playgroundUri
} catch (error: any) {
logger.error('Error in verifyAuthToken:', error)
throw new LogError(error.message)
}
}

View File

@ -37,6 +37,7 @@ export enum RIGHTS {
LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES',
OPEN_CREATIONS = 'OPEN_CREATIONS',
USER = 'USER',
GMS_USER_PLAYGROUND = 'GMS_USER_PLAYGROUND',
// Moderator
SEARCH_USERS = 'SEARCH_USERS',
ADMIN_CREATE_CONTRIBUTION = 'ADMIN_CREATE_CONTRIBUTION',

View File

@ -29,4 +29,5 @@ export const USER_RIGHTS = [
RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES,
RIGHTS.OPEN_CREATIONS,
RIGHTS.USER,
RIGHTS.GMS_USER_PLAYGROUND,
]

View File

@ -19,7 +19,7 @@ const constants = {
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v21.2024-01-06',
EXPECTED: 'v22.2024-03-14',
CURRENT: '',
},
}
@ -145,6 +145,8 @@ const gms = {
GMS_ACTIVE: process.env.GMS_ACTIVE === 'true' || false,
// koordinates of Illuminz-instance of GMS
GMS_URL: process.env.GMS_HOST ?? 'http://localhost:4044/',
// used as secret postfix attached at the gms community-auth-url endpoint ('/hook/gms/' + 'secret')
GMS_WEBHOOK_SECRET: process.env.GMS_WEBHOOK_SECRET ?? 'secret',
}
export const CONFIG = {

View File

@ -75,6 +75,7 @@ import { Location2Point } from './util/Location2Point'
import { setUserRole, deleteUserRole } from './util/modifyUserRole'
import { sendUserToGms } from './util/sendUserToGms'
import { validateAlias } from './util/validateAlias'
import { authenticateGmsUserSearch } from './util/authenticateGmsUserSearch'
const LANGUAGES = ['de', 'en', 'es', 'fr', 'nl']
const DEFAULT_LANGUAGE = 'de'
@ -655,6 +656,21 @@ export class UserResolver {
return elopageBuys
}
@Authorized([RIGHTS.GMS_USER_PLAYGROUND])
@Query(() => String)
async authUserForGmsUserSearch(@Ctx() context: Context): Promise<string> {
logger.info(`authUserForGmsUserSearch()...`)
const dbUser = getUser(context)
let gmsPlaygroundUri: string
if (context.token) {
gmsPlaygroundUri = await authenticateGmsUserSearch(context.token, dbUser)
logger.debug('authUserForGmsUserSearch=', gmsPlaygroundUri)
} else {
throw new LogError('authUserForGmsUserSearch without token')
}
return gmsPlaygroundUri
}
@Authorized([RIGHTS.SEARCH_ADMIN_USERS])
@Query(() => SearchAdminUsersResult)
async searchAdminUsers(

View File

@ -0,0 +1,9 @@
import { User as DbUser } from '@entity/User'
import { verifyAuthToken } from '@/apis/gms/GmsClient'
export async function authenticateGmsUserSearch(token: string, dbUser: DbUser): Promise<string> {
const gmsPlaygroundUri = await verifyAuthToken(dbUser.communityUuid, token)
return gmsPlaygroundUri
}

View File

@ -13,6 +13,7 @@ import { schema } from '@/graphql/schema'
import { Connection } from '@/typeorm/connection'
import { checkDBVersion } from '@/typeorm/DBVersion'
import { elopageWebhook } from '@/webhook/elopage'
import { gmsWebhook } from '@/webhook/gms'
import { context as serverContext } from './context'
import { cors } from './cors'
@ -94,6 +95,10 @@ export const createServer = async (
// eslint-disable-next-line @typescript-eslint/no-misused-promises
app.post('/hook/elopage/' + CONFIG.WEBHOOK_ELOPAGE_SECRET, elopageWebhook)
// GMS Webhook
// eslint-disable-next-line @typescript-eslint/no-misused-promises
app.post('/hook/gms/' + CONFIG.GMS_WEBHOOK_SECRET, gmsWebhook)
// Apollo Server
const apollo = new ApolloServer({
schema: await schema(),

View File

@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { User as DbUser } from '@entity/User'
import { decode } from '@/auth/JWT'
import { backendLogger as logger } from '@/server/logger'
export const gmsWebhook = async (req: any, res: any): Promise<void> => {
logger.info('GMS Hook received', req.body)
const { token } = req.body
if (!token) {
logger.warn('gmsWebhook: missing token')
res.status(400).json({ message: 'false' })
return
}
const payload = await decode(token)
if (payload) {
const user = await DbUser.findOne({ where: { gradidoID: payload.gradidoID } })
if (!user) {
logger.warn('gmsWebhook: missing user')
res.status(400).json({ message: 'false' })
return
}
logger.info('gmsWebhook: authenticate user=', user)
}
logger.info('gmsWebhook: authentication successful')
res.status(200).json({ message: 'true' })
}