This commit is contained in:
+21
-1
@@ -1,6 +1,7 @@
|
||||
import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import type { Request } from 'express'
|
||||
import { prisma } from './db.js'
|
||||
|
||||
const LOGTO_JWKS_URL = process.env.LOGTO_JWKS_URL || 'https://auth.optovia.ru/oidc/jwks'
|
||||
const LOGTO_ISSUER = process.env.LOGTO_ISSUER || 'https://auth.optovia.ru/oidc'
|
||||
@@ -11,10 +12,13 @@ const jwks = createRemoteJWKSet(new URL(LOGTO_JWKS_URL))
|
||||
export interface AuthContext {
|
||||
userId?: string
|
||||
teamUuid?: string
|
||||
sessionToken?: string
|
||||
scopes: string[]
|
||||
isM2M?: boolean
|
||||
}
|
||||
|
||||
export const SESSION_TOKEN_PREFIX = 'optovia-session:'
|
||||
|
||||
function getBearerToken(req: Request): string {
|
||||
const auth = req.headers.authorization || ''
|
||||
if (!auth.startsWith('Bearer ')) throw new GraphQLError('Missing Bearer token', { extensions: { code: 'UNAUTHENTICATED' } })
|
||||
@@ -23,6 +27,14 @@ function getBearerToken(req: Request): string {
|
||||
return token
|
||||
}
|
||||
|
||||
function optionalBearerToken(req: Request): string | null {
|
||||
const auth = req.headers.authorization || ''
|
||||
if (!auth.startsWith('Bearer ')) return null
|
||||
const token = auth.slice(7)
|
||||
if (!token || token === 'undefined') return null
|
||||
return token
|
||||
}
|
||||
|
||||
function scopesFromPayload(payload: JWTPayload): string[] {
|
||||
const scope = payload.scope
|
||||
if (!scope) return []
|
||||
@@ -33,7 +45,15 @@ function scopesFromPayload(payload: JWTPayload): string[] {
|
||||
export async function publicContext(): Promise<AuthContext> { return { scopes: [] } }
|
||||
|
||||
export async function userContext(req: Request): Promise<AuthContext> {
|
||||
const token = getBearerToken(req)
|
||||
const token = optionalBearerToken(req)
|
||||
if (token === null) return { scopes: [] }
|
||||
if (token.startsWith(SESSION_TOKEN_PREFIX)) {
|
||||
const session = await prisma.authSession.findUnique({ where: { token }, include: { user: true } })
|
||||
if (session === null || session.revokedAt !== null || session.expiresAt <= new Date()) {
|
||||
throw new GraphQLError('Session expired', { extensions: { code: 'UNAUTHENTICATED' } })
|
||||
}
|
||||
return { userId: session.user.username, sessionToken: token, scopes: ['teams:user'] }
|
||||
}
|
||||
const { payload } = await jwtVerify(token, jwks, { issuer: LOGTO_ISSUER })
|
||||
return { userId: payload.sub, scopes: [] }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user