Files
tvone-api/src/module/auth/keycloak.strategy.ts
T

40 lines
1.3 KiB
TypeScript
Raw Normal View History

2026-04-17 13:34:57 +01:00
import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";
import * as jwksRsa from "jwks-rsa";
@Injectable()
export class KeycloakStrategy extends PassportStrategy(Strategy, "keycloak") {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
// 🔑 Get signing key from Keycloak
secretOrKeyProvider: jwksRsa.passportJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri:
"https://keycloak.petermaquiran.xyz/realms/tvone/protocol/openid-connect/certs",
}),
//audience: "tvone-web", // your Keycloak clientId
issuer: "https://keycloak.petermaquiran.xyz/realms/tvone",
algorithms: ["RS256"],
});
}
async validate(payload: any) {
return {
userId: payload.sub,
email: payload.email,
2026-04-17 14:53:21 +01:00
name: payload.name,
// Google profile image is usually in 'picture'
email_verified: payload.email_verified,
picture: payload.picture || `https://profiles.google.com/s2/photos/profile/${payload.email}`,
2026-04-17 13:34:57 +01:00
roles: payload.realm_access?.roles || [],
2026-04-17 14:53:21 +01:00
// Keep raw for debugging other custom claims
2026-04-17 13:34:57 +01:00
raw: payload,
};
}
}