From 64c94ca9f4b579a8060e8e6d6e13def6c5a54af7 Mon Sep 17 00:00:00 2001 From: noahspannbauer Date: Tue, 2 Dec 2025 17:10:45 -0600 Subject: [PATCH] switching to auth0 (#103) --- api/src/app.module.ts | 22 +++++++++---------- .../interfaces/customJwtPayload.interface.ts | 2 +- api/src/log/log.interceptor.ts | 6 ++--- api/src/pilot/pilot.interceptor.ts | 6 ++--- client/package.json | 1 - client/src/auth/oidcConfig.ts | 8 ++++--- client/src/hooks/userRole/UseUserRole.tsx | 3 ++- client/src/vite-env.d.ts | 1 + package-lock.json | 2 +- 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/api/src/app.module.ts b/api/src/app.module.ts index 378dbb6..eba2dc7 100644 --- a/api/src/app.module.ts +++ b/api/src/app.module.ts @@ -32,17 +32,17 @@ import { join } from 'path'; }), HealthModule, LogModule, - MsGraphModule.registerAsync({ - inject: [ConfigService], - imports: [ConfigModule], - useFactory: async (configService: ConfigService) => { - return { - clientId: configService.get('clientId'), - clientSecret: configService.get('clientSecret'), - tenantId: configService.get('tenantId') - } - } - }), + // MsGraphModule.registerAsync({ + // inject: [ConfigService], + // imports: [ConfigModule], + // useFactory: async (configService: ConfigService) => { + // return { + // clientId: configService.get('clientId'), + // clientSecret: configService.get('clientSecret'), + // tenantId: configService.get('tenantId') + // } + // } + // }), PilotModule, ServeStaticModule.forRoot({ rootPath: join(__dirname, '../..', 'client', 'dist') diff --git a/api/src/interfaces/customJwtPayload.interface.ts b/api/src/interfaces/customJwtPayload.interface.ts index 17b3c82..a4dc6f0 100644 --- a/api/src/interfaces/customJwtPayload.interface.ts +++ b/api/src/interfaces/customJwtPayload.interface.ts @@ -1,5 +1,5 @@ import { JwtPayload } from "jwt-decode"; export interface CustomJwtPayload extends JwtPayload { - roles: string[]; + permissions: string[]; } \ No newline at end of file diff --git a/api/src/log/log.interceptor.ts b/api/src/log/log.interceptor.ts index 15676dc..9013c3a 100644 --- a/api/src/log/log.interceptor.ts +++ b/api/src/log/log.interceptor.ts @@ -2,7 +2,6 @@ import { CallHandler, ExecutionContext, NestInterceptor, UnauthorizedException } import { Observable, map } from 'rxjs'; import { LogEntity } from './log.entity'; import { jwtDecode } from 'jwt-decode'; -import { CustomJwtPayload } from 'src/interfaces/customJwtPayload.interface'; import { IS_PUBLIC_KEY } from '@noahspan/noahspan-modules'; import { Reflector } from '@nestjs/core'; @@ -38,9 +37,10 @@ export class LogInterceptor implements NestInterceptor { if (req.headers.authorization) { const authHeader = req.headers.authorization; const token = authHeader && authHeader.split(' ')[1]; - const jwtPayload: CustomJwtPayload = jwtDecode(token); + const jwtPayload = jwtDecode(token); + const rolesKeyName = Object.keys(jwtPayload).find((key) => key.includes('roles')); - if (jwtPayload.roles.includes('Flying.Read')) { + if (jwtPayload[rolesKeyName].includes('Flying.Read')) { const logs = limitData(data); return logs; diff --git a/api/src/pilot/pilot.interceptor.ts b/api/src/pilot/pilot.interceptor.ts index 5ef7036..1e9cb5c 100644 --- a/api/src/pilot/pilot.interceptor.ts +++ b/api/src/pilot/pilot.interceptor.ts @@ -1,7 +1,6 @@ import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common'; import { jwtDecode } from 'jwt-decode'; import { Observable, map } from 'rxjs'; -import { CustomJwtPayload } from 'src/interfaces/customJwtPayload.interface'; import { PilotEntity } from './pilot.entity'; import { IS_PUBLIC_KEY } from '@noahspan/noahspan-modules'; import { Reflector } from '@nestjs/core'; @@ -30,9 +29,10 @@ export class PilotInterceptor implements NestInterceptor { if (req.headers.authorization) { const authHeader = req.headers.authorization; const token = authHeader && authHeader.split(' ')[1]; - const jwtPayload: CustomJwtPayload = jwtDecode(token); + const jwtPayload = jwtDecode(token); + const rolesKeyName = Object.keys(jwtPayload).find((key) => key.includes('roles')); - if (jwtPayload.roles.includes('Flying.Read')) { + if (jwtPayload[rolesKeyName].includes('Flying.Read')) { const pilots = limitData(data) return pilots; diff --git a/client/package.json b/client/package.json index a89acef..1e4ea21 100644 --- a/client/package.json +++ b/client/package.json @@ -20,7 +20,6 @@ "@tailwindcss/vite": "^4.1.13", "@tanstack/react-table": "^8.21.3", "axios": "^1.7.2", - "daisyui": "^5.1.10", "dotenv": "^16.4.7", "framer-motion": "^12.23.24", "leaflet": "^1.9.4", diff --git a/client/src/auth/oidcConfig.ts b/client/src/auth/oidcConfig.ts index 81edc53..d6d3ec7 100644 --- a/client/src/auth/oidcConfig.ts +++ b/client/src/auth/oidcConfig.ts @@ -1,11 +1,13 @@ import { createReactOidc } from "oidc-spa/react"; export const { OidcProvider, useOidc, getOidc } = createReactOidc(async () => ({ - issuerUri: `https://login.microsoftonline.com/${import.meta.env.VITE_TENANT_ID}/v2.0`, + issuerUri: import.meta.env.VITE_ISSUER_URI, clientId: import.meta.env.VITE_CLIENT_ID, homeUrl: import.meta.env.VITE_BASE_URL, - scopes: ['email', 'openid', 'profile', `api://${import.meta.env.VITE_CLIENT_ID}/user_impersonation`], autoLogin: false, postLoginRedirectUrl: '/', - noIframe: true + noIframe: true, + extraQueryParams: { + audience: "api://flying-test-api" + } })); \ No newline at end of file diff --git a/client/src/hooks/userRole/UseUserRole.tsx b/client/src/hooks/userRole/UseUserRole.tsx index a1dd8f9..66df1db 100644 --- a/client/src/hooks/userRole/UseUserRole.tsx +++ b/client/src/hooks/userRole/UseUserRole.tsx @@ -8,7 +8,8 @@ export const useUserRole = () => { useEffect(() => { if (isUserLoggedIn && decodedIdToken) { - const idTokenRoles: string[] = decodedIdToken!.roles as string[]; + const rolesKeyName: string | undefined = Object.keys(decodedIdToken).find((key) => key.includes('roles')); + const idTokenRoles: string[] = decodedIdToken[rolesKeyName!] as string[]; let newUserRole: string | undefined; diff --git a/client/src/vite-env.d.ts b/client/src/vite-env.d.ts index bb14f06..4469250 100644 --- a/client/src/vite-env.d.ts +++ b/client/src/vite-env.d.ts @@ -3,6 +3,7 @@ interface ImportMetaEnv { readonly VITE_BASE_URL: string; readonly VITE_CLIENT_ID: string; + readonly VITE_ISSUER_URI: string; readonly VITE_TENANT_ID: string; } diff --git a/package-lock.json b/package-lock.json index a40032c..5c59a2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,7 +91,6 @@ "@tailwindcss/vite": "^4.1.13", "@tanstack/react-table": "^8.21.3", "axios": "^1.7.2", - "daisyui": "^5.1.10", "dotenv": "^16.4.7", "framer-motion": "^12.23.24", "leaflet": "^1.9.4", @@ -230,6 +229,7 @@ "version": "5.1.10", "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.1.10.tgz", "integrity": "sha512-p1J/HME2WmaSiy6u2alIbeP3gd5PNVft3+6Bdll0BRSm/UdI4084+pD01LxFug/5wGexNewWqbcEL6nB2n2o+Q==", + "peer": true, "funding": { "url": "https://github.com/saadeghi/daisyui?sponsor=1" }