46 lines
1.8 KiB
TypeScript
46 lines
1.8 KiB
TypeScript
import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { PassportStrategy } from '@nestjs/passport';
|
|
import { passportJwtSecret } from 'jwks-rsa';
|
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
|
import { ExtractJwt, Strategy } from 'passport-jwt';
|
|
import { Logger } from 'winston';
|
|
import { JwtPayload, JwtUser } from './models/main.model';
|
|
@Injectable()
|
|
export class JwtStrategy extends PassportStrategy(Strategy) {
|
|
constructor(
|
|
configService: ConfigService,
|
|
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
|
) {
|
|
const realm = configService.get<string>('REALM');
|
|
super({
|
|
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
ignoreExpiration: false,
|
|
secretOrKeyProvider: passportJwtSecret({
|
|
cache: true,
|
|
rateLimit: true,
|
|
jwksRequestsPerMinute: 5,
|
|
jwksUri: `https://auth.bizmatch.net/realms/${realm}/protocol/openid-connect/certs`,
|
|
}),
|
|
audience: 'account', // Keycloak Client ID
|
|
authorize: '',
|
|
issuer: `https://auth.bizmatch.net/realms/${realm}`,
|
|
algorithms: ['RS256'],
|
|
});
|
|
}
|
|
|
|
async validate(payload: JwtPayload): Promise<JwtUser> {
|
|
if (!payload) {
|
|
this.logger.error('Invalid payload');
|
|
throw new UnauthorizedException();
|
|
}
|
|
if (!payload.sub || !payload.preferred_username) {
|
|
this.logger.error('Missing required claims');
|
|
throw new UnauthorizedException();
|
|
}
|
|
const result = { userId: payload.sub, firstname: payload.given_name, lastname: payload.family_name, username: payload.preferred_username, roles: payload.realm_access?.roles };
|
|
this.logger.info(`JWT User: ${JSON.stringify(result)}`); // Debugging: JWT Payload anzeigen
|
|
return result;
|
|
}
|
|
}
|