mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 17:08:18 +00:00
feat: ( redirect ) add redirect url based on the domain name
This commit is contained in:
@@ -2,6 +2,7 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Headers,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Post,
|
||||
@@ -19,6 +20,7 @@ import type { TCurrentUser } from "@tria-plc/api-common/modules/auth/types/curre
|
||||
import { IsPublic } from "@tria-plc/api-common/modules/auth/decorators/public.decorator";
|
||||
import { JwtGuard } from "../../common/jwt.guard";
|
||||
import { OptionalJwtGuard } from "./optional-jwt.guard";
|
||||
import { resolveAllowedOrigin } from "../../common/utils/redirect-origin.util";
|
||||
import {
|
||||
CompleteVerificationResultDto,
|
||||
StartVerificationDto,
|
||||
@@ -68,12 +70,20 @@ export class VerifaydaController {
|
||||
async start(
|
||||
@Body() dto: StartVerificationDto,
|
||||
@Req() req: RequestWithOptionalUser,
|
||||
@Headers("origin") origin?: string,
|
||||
@Headers("referer") referer?: string,
|
||||
@Headers("x-frontend-base-url") frontendBaseUrl?: string,
|
||||
): Promise<{ authorizationUrl: string }> {
|
||||
const authorizationUrl = await this.service.startVerification({
|
||||
purpose: dto.purpose ?? "VERIFY",
|
||||
platform: dto.platform ?? "WEB",
|
||||
userId: req.user?.id,
|
||||
wantsPasswordSetup: dto.wantsPasswordSetup ?? false,
|
||||
// WEB redirect_uri host follows the domain the user is on — Origin, then
|
||||
// Referer, then the X-Frontend-Base-URL header — validated against the
|
||||
// allowlist. Both domain variants must be registered with eSignet or the
|
||||
// login is rejected.
|
||||
requestOrigin: resolveAllowedOrigin(origin, referer, frontendBaseUrl),
|
||||
});
|
||||
return { authorizationUrl };
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
generateState,
|
||||
} from './utils/pkce.util';
|
||||
import { generateClientAssertion } from './utils/client-assertion.util';
|
||||
import { rebaseUrlOrigin } from '../../common/utils/redirect-origin.util';
|
||||
import { VerifaydaCallbackDto, VerificationStatusDto } from './verifayda.dto';
|
||||
import {
|
||||
FaydaTokenExchangeException,
|
||||
@@ -49,6 +50,13 @@ export interface StartVerificationInput {
|
||||
platform?: FaydaPlatform;
|
||||
userId?: string; // iamUserId of the authenticated user, if any
|
||||
wantsPasswordSetup?: boolean;
|
||||
/**
|
||||
* Allowlisted browser origin the request came from (e.g. https://bookingedr.et
|
||||
* or https://passenger.edrsc.com), already validated by the controller. For
|
||||
* WEB sessions the eSignet redirect_uri host is swapped to this so the user
|
||||
* lands back on the same domain. Null/undefined keeps the configured default.
|
||||
*/
|
||||
requestOrigin?: string | null;
|
||||
}
|
||||
|
||||
export interface FaydaUserSummary {
|
||||
@@ -145,12 +153,26 @@ export class VerifaydaService {
|
||||
Date.now() + this.faydaConfig.sessionTtlMinutes * 60_000,
|
||||
);
|
||||
|
||||
const platform = input.platform ?? 'WEB';
|
||||
// WEB sessions follow the domain the user came in on (bookingedr.et vs
|
||||
// passenger.edrsc.com); MOBILE always uses the native base redirect_uri.
|
||||
// Persist the exact URI so token exchange at /complete reuses it verbatim —
|
||||
// eSignet requires the redirect_uri to match between authorize and token.
|
||||
const redirectUri =
|
||||
platform === 'MOBILE'
|
||||
? this.redirectUriForPlatform('MOBILE')
|
||||
: rebaseUrlOrigin(
|
||||
this.faydaConfig.webRedirectUri,
|
||||
input.requestOrigin ?? null,
|
||||
) ?? this.faydaConfig.webRedirectUri;
|
||||
|
||||
await this.prisma.faydaVerificationSession.create({
|
||||
data: {
|
||||
state,
|
||||
codeVerifier,
|
||||
purpose: input.purpose,
|
||||
platform: input.platform ?? 'WEB',
|
||||
platform,
|
||||
redirectUri,
|
||||
saveToAccount: input.wantsPasswordSetup ?? false,
|
||||
iamUserId: input.userId ?? null,
|
||||
expiresAt,
|
||||
@@ -158,13 +180,13 @@ export class VerifaydaService {
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Fayda verification started: purpose=${input.purpose} platform=${input.platform ?? 'WEB'} userId=${input.userId ?? 'none'}`,
|
||||
`Fayda verification started: purpose=${input.purpose} platform=${platform} userId=${input.userId ?? 'none'} redirectUri=${redirectUri}`,
|
||||
);
|
||||
|
||||
return this.buildAuthorizationUrl({
|
||||
state,
|
||||
codeChallenge,
|
||||
redirectUri: this.redirectUriForPlatform(input.platform ?? 'WEB'),
|
||||
redirectUri,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -224,7 +246,11 @@ export class VerifaydaService {
|
||||
const tokens = await this.exchangeCodeForTokens(
|
||||
query.code,
|
||||
session.codeVerifier,
|
||||
this.redirectUriForPlatform(session.platform as FaydaPlatform),
|
||||
// Reuse the exact redirect_uri sent at authorize (persisted on the
|
||||
// session). Fall back to the platform default for sessions created
|
||||
// before this column existed.
|
||||
session.redirectUri ??
|
||||
this.redirectUriForPlatform(session.platform as FaydaPlatform),
|
||||
);
|
||||
const userInfo = await this.fetchUserInfo(tokens.access_token);
|
||||
const normalized = this.normalizeUserInfo(userInfo);
|
||||
|
||||
Reference in New Issue
Block a user