mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
Merge branch 'dev-1' into dev
This commit is contained in:
commit
d41d060bb3
1770 changed files with 168028 additions and 31031 deletions
|
|
@ -5,10 +5,18 @@ import {
|
|||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { jwtVerify, createRemoteJWKSet, type JWTPayload } from 'jose';
|
||||
|
||||
/**
|
||||
* JWT Auth Guard using JWKS (Better Auth compatible)
|
||||
*
|
||||
* Uses jose library with JWKS endpoint for EdDSA token verification.
|
||||
* This is the correct approach for Better Auth which uses EdDSA keys.
|
||||
*/
|
||||
@Injectable()
|
||||
export class JwtAuthGuard implements CanActivate {
|
||||
private jwks: ReturnType<typeof createRemoteJWKSet> | null = null;
|
||||
|
||||
constructor(private configService: ConfigService) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
|
|
@ -20,28 +28,31 @@ export class JwtAuthGuard implements CanActivate {
|
|||
}
|
||||
|
||||
try {
|
||||
const publicKey = this.configService.get<string>('jwt.publicKey');
|
||||
if (!publicKey) {
|
||||
throw new UnauthorizedException('JWT configuration error');
|
||||
// Lazy initialize JWKS
|
||||
if (!this.jwks) {
|
||||
const baseUrl = this.configService.get<string>('BASE_URL') || 'http://localhost:3001';
|
||||
const jwksUrl = new URL('/api/v1/auth/jwks', baseUrl);
|
||||
this.jwks = createRemoteJWKSet(jwksUrl);
|
||||
}
|
||||
const audience = this.configService.get<string>('jwt.audience');
|
||||
const issuer = this.configService.get<string>('jwt.issuer');
|
||||
|
||||
const payload = jwt.verify(token, publicKey, {
|
||||
algorithms: ['RS256'],
|
||||
audience,
|
||||
const issuer = this.configService.get<string>('jwt.issuer') || 'manacore';
|
||||
const audience = this.configService.get<string>('jwt.audience') || 'manacore';
|
||||
|
||||
const { payload } = await jwtVerify(token, this.jwks, {
|
||||
issuer,
|
||||
}) as jwt.JwtPayload;
|
||||
audience,
|
||||
});
|
||||
|
||||
// Attach user to request
|
||||
request.user = {
|
||||
userId: payload.sub,
|
||||
email: payload.email,
|
||||
role: payload.role,
|
||||
email: payload.email as string,
|
||||
role: payload.role as string,
|
||||
};
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.debug('[JwtAuthGuard] Token verification failed:', error);
|
||||
throw new UnauthorizedException('Invalid token');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import type { CanActivate, ExecutionContext } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { jwtVerify, createRemoteJWKSet } from 'jose';
|
||||
|
||||
/**
|
||||
* Optional authentication guard
|
||||
* Attaches user to request if valid token is present, but doesn't require it
|
||||
* Optional authentication guard using JWKS (Better Auth compatible)
|
||||
*
|
||||
* Attaches user to request if valid token is present, but doesn't require it.
|
||||
* Uses jose library with JWKS endpoint for EdDSA token verification.
|
||||
*/
|
||||
@Injectable()
|
||||
export class OptionalAuthGuard implements CanActivate {
|
||||
private jwks: ReturnType<typeof createRemoteJWKSet> | null = null;
|
||||
|
||||
constructor(private configService: ConfigService) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
|
|
@ -22,26 +26,26 @@ export class OptionalAuthGuard implements CanActivate {
|
|||
}
|
||||
|
||||
try {
|
||||
const publicKey = this.configService.get<string>('jwt.publicKey');
|
||||
if (!publicKey) {
|
||||
request.user = null;
|
||||
return true;
|
||||
// Lazy initialize JWKS
|
||||
if (!this.jwks) {
|
||||
const baseUrl = this.configService.get<string>('BASE_URL') || 'http://localhost:3001';
|
||||
const jwksUrl = new URL('/api/v1/auth/jwks', baseUrl);
|
||||
this.jwks = createRemoteJWKSet(jwksUrl);
|
||||
}
|
||||
|
||||
const audience = this.configService.get<string>('jwt.audience');
|
||||
const issuer = this.configService.get<string>('jwt.issuer');
|
||||
const issuer = this.configService.get<string>('jwt.issuer') || 'manacore';
|
||||
const audience = this.configService.get<string>('jwt.audience') || 'manacore';
|
||||
|
||||
const payload = jwt.verify(token, publicKey, {
|
||||
algorithms: ['RS256'],
|
||||
audience,
|
||||
const { payload } = await jwtVerify(token, this.jwks, {
|
||||
issuer,
|
||||
}) as jwt.JwtPayload;
|
||||
audience,
|
||||
});
|
||||
|
||||
// Attach user to request
|
||||
request.user = {
|
||||
userId: payload.sub,
|
||||
email: payload.email,
|
||||
role: payload.role,
|
||||
email: payload.email as string,
|
||||
role: payload.role as string,
|
||||
};
|
||||
} catch {
|
||||
// Invalid token - allow request but no user
|
||||
|
|
|
|||
|
|
@ -10,12 +10,18 @@ async function bootstrap() {
|
|||
|
||||
const configService = app.get(ConfigService);
|
||||
|
||||
// Security middleware
|
||||
app.use(helmet());
|
||||
// Security middleware - configure helmet to allow CORS
|
||||
app.use(
|
||||
helmet({
|
||||
crossOriginResourcePolicy: { policy: 'cross-origin' },
|
||||
crossOriginOpenerPolicy: { policy: 'same-origin-allow-popups' },
|
||||
})
|
||||
);
|
||||
app.use(cookieParser());
|
||||
|
||||
// CORS configuration
|
||||
const corsOrigins = configService.get<string[]>('cors.origin') || [];
|
||||
console.log('📋 CORS Origins configured:', corsOrigins);
|
||||
app.enableCors({
|
||||
origin: corsOrigins,
|
||||
credentials: true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue