diff --git a/packages/api/src/apollo.ts b/packages/api/src/apollo.ts index 3ab478a45..2db7d48bb 100644 --- a/packages/api/src/apollo.ts +++ b/packages/api/src/apollo.ts @@ -24,6 +24,7 @@ import ScalarResolvers from './scalars' import * as Sentry from '@sentry/node' import { createPubSubClient } from './datalayer/pubsub' import { initModels } from './server' +import { claimsFromApiKey } from './utils/auth' const signToken = promisify(jwt.sign) const logger = buildLogger('app.dispatch') @@ -47,8 +48,12 @@ const contextFunc: ContextFunction = async ({ variables: req.body.variables, }) - if (token && jwt.verify(token, env.server.jwtSecret)) { - claims = jwt.decode(token) as Claims + if (token) { + jwt.verify(token, env.server.jwtSecret) && + (claims = jwt.decode(token) as Claims) + if (!claims) { + claims = await claimsFromApiKey(token) + } } async function setClaims( diff --git a/packages/api/src/utils/auth.ts b/packages/api/src/utils/auth.ts index a6814fb8b..f1581e1c4 100644 --- a/packages/api/src/utils/auth.ts +++ b/packages/api/src/utils/auth.ts @@ -1,5 +1,8 @@ import * as bcrypt from 'bcryptjs' import { v4 as uuidv4 } from 'uuid' +import { Claims } from '../resolvers/types' +import { getRepository } from '../entity/utils' +import { ApiKey } from '../entity/api_key' export const hashKey = (key: string, salt = 10) => { return bcrypt.hashSync(key, salt) @@ -13,3 +16,26 @@ export const generateApiKey = (): string => { // TODO: generate random string key return uuidv4() } + +export const claimsFromApiKey = async ( + key: string +): Promise => { + const hashedKey = hashKey(key) + const apiKey = await getRepository(ApiKey).findOne({ + where: { key: hashedKey }, + relations: ['user'], + }) + if (!apiKey) { + console.error('api key not found') + return undefined + } + + // update last used + await getRepository(ApiKey).update(apiKey.id, { usedAt: new Date() }) + + return { + uid: apiKey.user.id, + iat: new Date().getTime(), + exp: apiKey.expiresAt.getTime(), + } +}