targo-backend/src/identity-and-account/authentication/strategies/authentik.strategy.ts

64 lines
2.5 KiB
TypeScript

import { Strategy as OIDCStrategy, Profile, VerifyCallback } from 'passport-openidconnect';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { AuthentikAuthService } from '../services/authentik-auth.service';
import { ValidationError } from 'class-validator';
export interface AuthentikPayload {
iss: string; // Issuer
sub: string; // Subject (user ID)
aud: string; // Audience (client ID)
exp: number; // Expiration time (Unix)
iat: number; // Issued at time (Unix)
auth_time: number; // Time of authentication (Unix)
acr?: string; // Auth Context Class Reference
amr?: string[]; // Auth Method References (e.g., ['pwd'])
email: string;
email_verified: boolean;
name?: string;
given_name?: string;
preferred_username?: string;
nickname?: string;
groups?: string[];
}
@Injectable()
export class AuthentikStrategy extends PassportStrategy(OIDCStrategy, 'openidconnect', 8) {
constructor(private authentikAuthService: AuthentikAuthService) {
super({
issuer: process.env.AUTHENTIK_ISSUER || "ISSUER_MISSING",
clientID: process.env.AUTHENTIK_CLIENT_ID || 'CLIENT_ID_MISSING',
clientSecret: process.env.AUTHENTIK_CLIENT_SECRET || 'CLIENT_SECRET_MISSING',
callbackURL: process.env.AUTHENTIK_CALLBACK_URL || 'CALLBACK_URL_MISSING',
authorizationURL: process.env.AUTHENTIK_AUTH_URL || 'AUTH_URL_MISSING',
tokenURL: process.env.AUTHENTIK_TOKEN_URL || 'TOKEN_URL_MISSING',
userInfoURL: process.env.AUTHENTIK_USERINFO_URL || 'USERINFO_URL_MISSING',
scope: ['openid', 'email', 'profile', 'offline_access'],
},);
}
async validate(
_issuer: string,
profile: Profile,
_context: any,
_idToken: string,
_accessToken: string,
_refreshToken: string,
_params: any,
cb: VerifyCallback,
): Promise<any> {
try {
const email = profile.emails?.[0]?.value;
if (!email) return cb(new Error('Missing email in OIDC profile'), false);
const user = await this.authentikAuthService.validateUser(email);
if (!user) return cb(new Error('User not found'), false);
return cb(null, user);
} catch (err) {
return cb(err, false);
}
}
}