64 lines
2.5 KiB
TypeScript
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);
|
|
}
|
|
}
|
|
}
|