UNPKG

@accounter/server

Version:
120 lines 4.23 kB
import { __decorate, __metadata, __param } from "tslib"; import { Inject, Injectable, Scope } from 'graphql-modules'; import { createRemoteJWKSet, jwtVerify } from 'jose'; import { ENVIRONMENT, RAW_AUTH } from '../../../shared/tokens.js'; import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js'; // Global cache for JWKS functions to prevent re-fetching on every request const jwksCache = new Map(); let AuthContextV2Provider = class AuthContextV2Provider { rawAuth; db; env; constructor(rawAuth, db, env) { this.rawAuth = rawAuth; this.db = db; this.env = env; } async getAuthContext() { if (!this.rawAuth.authType) { return null; } if (this.rawAuth.authType === 'jwt') { return this.handleJwtAuth(); } if (this.rawAuth.authType === 'apiKey') { // Placeholder for Phase 7 return null; } return null; } async handleJwtAuth() { const token = this.rawAuth.token; if (!token) { return null; } try { if (!this.env.auth0) { throw new Error('Auth0 configuration is missing'); } // 1. Verify JWT signature using Auth0 JWKS const domain = this.env.auth0.domain; let JWKS = jwksCache.get(domain); if (!JWKS) { JWKS = createRemoteJWKSet(new URL(`https://${domain}/.well-known/jwks.json`)); jwksCache.set(domain, JWKS); } const { payload } = await jwtVerify(token, JWKS, { issuer: `https://${domain}/`, audience: this.env.auth0.audience, }); // 2. Extract Auth0 user ID const auth0UserId = payload.sub; if (!auth0UserId) { console.error('AuthContextV2: Missing sub claim in JWT'); return null; } // 3. Map to local user and business const userContext = await this.mapAuth0UserToLocal(auth0UserId); if (!userContext) { console.warn(`AuthContextV2: User not found/linked in local DB: ${auth0UserId}`); return null; } return { authType: 'jwt', // Will be treated as AuthType token, user: { userId: userContext.userId, roleId: userContext.roleId, email: payload.email ?? '', auth0UserId, permissions: payload.permissions ?? [], emailVerified: payload.email_verified ?? false, permissionsVersion: 0, }, tenant: { businessId: userContext.businessId, roleId: userContext.roleId, }, accessTokenExpiresAt: payload.exp, }; } catch (error) { console.error('AuthContextV2: JWT verification failed', error); return null; } } async mapAuth0UserToLocal(auth0UserId) { const query = ` SELECT bu.user_id, bu.business_id, bu.role_id FROM accounter_schema.business_users bu WHERE bu.auth0_user_id = $1 LIMIT 1 `; try { const result = await this.db.query(query, [auth0UserId]); if (result.rowCount === 0) { return null; } const row = result.rows[0]; return { userId: row.user_id, businessId: row.business_id, roleId: row.role_id, }; } catch (error) { console.error('AuthContextV2: DB lookup failed', error); throw error; } } }; AuthContextV2Provider = __decorate([ Injectable({ scope: Scope.Operation, }), __param(0, Inject(RAW_AUTH)), __param(2, Inject(ENVIRONMENT)), __metadata("design:paramtypes", [Object, TenantAwareDBClient, Object]) ], AuthContextV2Provider); export { AuthContextV2Provider }; //# sourceMappingURL=auth-context-v2.provider.js.map