feat(auth): secure backend authentication modes
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { env } from '../config/env';
|
||||
import { AppError } from '../errors/app-error';
|
||||
import {
|
||||
findByEmail,
|
||||
findByMicrosoftId,
|
||||
UtilisateurAvecRole,
|
||||
} from '../repositories/utilisateur.repository';
|
||||
import { AuthenticatedUser } from '../types/authenticated-user';
|
||||
import { verifyAzureAccessToken } from './azure-token.service';
|
||||
|
||||
export interface AuthenticationHeaders {
|
||||
authorization?: string;
|
||||
demoEmail?: string;
|
||||
}
|
||||
|
||||
function toAuthenticatedUser(utilisateur: UtilisateurAvecRole): AuthenticatedUser {
|
||||
return {
|
||||
id: utilisateur.id,
|
||||
email: utilisateur.email,
|
||||
roleCode: utilisateur.role.code,
|
||||
campusId: utilisateur.campusId,
|
||||
};
|
||||
}
|
||||
|
||||
function bearerToken(authorization: string | undefined): string {
|
||||
const match = authorization?.match(/^Bearer\s+(\S+)$/i);
|
||||
if (!match) {
|
||||
throw new AppError(401, 'Jeton Bearer requis');
|
||||
}
|
||||
|
||||
return match[1];
|
||||
}
|
||||
|
||||
async function authenticateDemo(email: string | undefined): Promise<UtilisateurAvecRole | null> {
|
||||
if (!email) {
|
||||
throw new AppError(401, 'En-tete x-user-email requis en mode demo');
|
||||
}
|
||||
|
||||
return findByEmail(email.trim().toLowerCase());
|
||||
}
|
||||
|
||||
async function authenticateAzure(
|
||||
authorization: string | undefined,
|
||||
): Promise<UtilisateurAvecRole | null> {
|
||||
const identity = await verifyAzureAccessToken(bearerToken(authorization));
|
||||
const byMicrosoftId = await findByMicrosoftId(identity.microsoftId);
|
||||
|
||||
if (byMicrosoftId) {
|
||||
return byMicrosoftId;
|
||||
}
|
||||
|
||||
return findByEmail(identity.email);
|
||||
}
|
||||
|
||||
export async function authenticateUser(
|
||||
headers: AuthenticationHeaders,
|
||||
): Promise<AuthenticatedUser> {
|
||||
const utilisateur =
|
||||
env.auth.mode === 'azure'
|
||||
? await authenticateAzure(headers.authorization)
|
||||
: await authenticateDemo(headers.demoEmail);
|
||||
|
||||
if (!utilisateur || !utilisateur.actif) {
|
||||
throw new AppError(401, 'Utilisateur non reconnu');
|
||||
}
|
||||
|
||||
return toAuthenticatedUser(utilisateur);
|
||||
}
|
||||
Reference in New Issue
Block a user