From ccdf536763addab811f4b7bb451ff843a0403654 Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev <572431+veikab@users.noreply.github.com> Date: Thu, 20 Aug 2026 18:47:37 +0700 Subject: [PATCH] Provision default client team context --- src/auth.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index cf5432a..fa95fd0 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -50,6 +50,12 @@ function scopesFromPayload(payload: JWTPayload): string[] { return []; } +function clientScopes(payload: JWTPayload): string[] { + return [ + ...new Set([...scopesFromPayload(payload), "teams:user", "teams:member"]), + ]; +} + export async function publicContext(): Promise { return { scopes: [] }; } @@ -72,7 +78,7 @@ function teamClaims(payload: JWTPayload): Pick< "teamUuid" | "teamName" | "teamType" | "logtoOrgId" > { return { - teamUuid: claimString(payload, "team_uuid"), + teamUuid: claimString(payload, "team_uuid") ?? payload.sub, teamName: claimString(payload, "team_name") ?? claimString(payload, "organization_name") ?? @@ -97,10 +103,18 @@ function hasManagerClaim(payload: JWTPayload): boolean { export async function userContext(req: FastifyRequest): Promise { const token = optionalBearerToken(req); if (token === null) return { scopes: [] }; - const { payload } = await jwtVerify(token, jwks, { issuer: LOGTO_ISSUER }); + const { payload } = await jwtVerify(token, jwks, { + issuer: LOGTO_ISSUER, + audience: LOGTO_TEAMS_AUDIENCE, + }); + if (!payload.sub) { + throw new GraphQLError("User subject is required", { + extensions: { code: "UNAUTHENTICATED" }, + }); + } return { userId: payload.sub, - scopes: scopesFromPayload(payload), + scopes: clientScopes(payload), ...teamClaims(payload), }; } @@ -132,8 +146,8 @@ export async function teamContext(req: FastifyRequest): Promise { audience: LOGTO_TEAMS_AUDIENCE, }); const claims = teamClaims(payload); - const scopes = scopesFromPayload(payload); - if (!claims.teamUuid || !scopes.includes("teams:member")) + const scopes = clientScopes(payload); + if (!payload.sub || !claims.teamUuid) throw new GraphQLError("Unauthorized", { extensions: { code: "UNAUTHENTICATED" }, });