75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import {
|
|
ExpressController,
|
|
type RequestWithAuth,
|
|
UnauthorizedApiError,
|
|
} from "@erp/core/api";
|
|
import { EmailAddress, UniqueID } from "@repo/rdx-ddd";
|
|
import type { NextFunction, Request, Response } from "express";
|
|
|
|
import type { IAccessTokenVerifier, IAccountRepository } from "../../../application";
|
|
|
|
function parseBearerToken(authorization?: string): string | undefined {
|
|
if (!authorization) {
|
|
return undefined;
|
|
}
|
|
|
|
const [scheme, token] = authorization.split(" ");
|
|
if (scheme?.toLowerCase() !== "bearer") {
|
|
return undefined;
|
|
}
|
|
|
|
return token?.trim() || undefined;
|
|
}
|
|
|
|
export function authenticateUser(params: {
|
|
accessTokenVerifier: IAccessTokenVerifier;
|
|
accountRepository: IAccountRepository;
|
|
}) {
|
|
return async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const authorization = req.get("authorization");
|
|
const token = parseBearerToken(authorization);
|
|
|
|
if (!token) {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
|
|
const verifiedTokenResult = await params.accessTokenVerifier.verify(token);
|
|
if (verifiedTokenResult.isFailure) {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
|
|
const accountIdResult = UniqueID.create(verifiedTokenResult.data.accountId);
|
|
if (accountIdResult.isFailure) {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
|
|
const accountResult = await params.accountRepository.findById(accountIdResult.data);
|
|
if (accountResult.isFailure || accountResult.data.isNone()) {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
|
|
const account = accountResult.data.unwrap();
|
|
const canAuthenticateResult = account.canAuthenticate();
|
|
if (canAuthenticateResult.isFailure) {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
|
|
const emailResult = EmailAddress.create(verifiedTokenResult.data.email);
|
|
if (emailResult.isFailure) {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
|
|
(req as RequestWithAuth).user = {
|
|
userId: account.id,
|
|
email: emailResult.data,
|
|
roles: [],
|
|
};
|
|
|
|
return next();
|
|
} catch {
|
|
return ExpressController.errorResponse(new UnauthorizedApiError("Unauthorized"), req, res);
|
|
}
|
|
};
|
|
}
|