fix and update
This commit is contained in:
@@ -2,6 +2,15 @@ import type { Request } from 'express';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { CoreGrpcService } from '../core-grpc.service';
|
||||
import { resolveFrontendUrl, resolveOAuthIssuer } from './oauth-issuer';
|
||||
import {
|
||||
hostsMatch,
|
||||
normalizePublicBaseUrl,
|
||||
preferBrowserReachableBase,
|
||||
readRequestHost,
|
||||
readRequestProto,
|
||||
resolvePublicApiBaseFromRequest,
|
||||
resolvePublicFrontendBaseFromRequest
|
||||
} from './public-url';
|
||||
|
||||
export interface FedcmEndpoints {
|
||||
issuer: string;
|
||||
@@ -16,94 +25,9 @@ export interface FedcmEndpoints {
|
||||
webIdentityUrl: string;
|
||||
}
|
||||
|
||||
function normalizeBaseUrl(url: string) {
|
||||
return url.trim().replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
function readRequestHost(req?: Request): string | undefined {
|
||||
if (!req) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const forwarded = req.headers['x-forwarded-host'];
|
||||
const host = (Array.isArray(forwarded) ? forwarded[0] : forwarded) ?? req.headers.host;
|
||||
return host?.split(',')[0]?.trim() || undefined;
|
||||
}
|
||||
|
||||
function readRequestProto(req?: Request): string {
|
||||
if (!req) {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
const forwarded = req.headers['x-forwarded-proto'];
|
||||
const proto = (Array.isArray(forwarded) ? forwarded[0] : forwarded) ?? req.protocol;
|
||||
return proto?.split(',')[0]?.trim() || 'https';
|
||||
}
|
||||
|
||||
function hostsMatch(a: string, b: string) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return a === 'localhost' && b === 'localhost';
|
||||
}
|
||||
|
||||
function resolveSameOriginFrontend(storedFrontend: string, req?: Request): string {
|
||||
const host = readRequestHost(req);
|
||||
if (!host) {
|
||||
return storedFrontend;
|
||||
}
|
||||
|
||||
const requestOrigin = normalizeBaseUrl(`${readRequestProto(req)}://${host}`);
|
||||
|
||||
try {
|
||||
const frontendUrl = new URL(storedFrontend);
|
||||
const requestUrl = new URL(requestOrigin);
|
||||
|
||||
if (hostsMatch(frontendUrl.hostname, requestUrl.hostname)) {
|
||||
return requestOrigin;
|
||||
}
|
||||
} catch {
|
||||
return storedFrontend;
|
||||
}
|
||||
|
||||
return storedFrontend;
|
||||
}
|
||||
|
||||
export function resolveSameOriginIssuer(storedIssuer: string, storedFrontend: string, req?: Request): string {
|
||||
const host = readRequestHost(req);
|
||||
if (!host) {
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
const requestOrigin = normalizeBaseUrl(`${readRequestProto(req)}://${host}`);
|
||||
const sameOriginApi = `${requestOrigin}/idp-api`;
|
||||
|
||||
try {
|
||||
const issuerUrl = new URL(storedIssuer);
|
||||
const frontendUrl = new URL(storedFrontend);
|
||||
const requestUrl = new URL(requestOrigin);
|
||||
|
||||
const hostMatches =
|
||||
hostsMatch(issuerUrl.hostname, requestUrl.hostname) || hostsMatch(frontendUrl.hostname, requestUrl.hostname);
|
||||
|
||||
if (!hostMatches) {
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
if (normalizeBaseUrl(storedIssuer) !== sameOriginApi) {
|
||||
return sameOriginApi;
|
||||
}
|
||||
} catch {
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
function buildFedcmEndpointUrls(issuer: string, frontendUrl: string) {
|
||||
const base = normalizeBaseUrl(issuer);
|
||||
const front = normalizeBaseUrl(frontendUrl);
|
||||
const base = normalizePublicBaseUrl(issuer);
|
||||
const front = normalizePublicBaseUrl(frontendUrl);
|
||||
|
||||
let webIdentityOrigin = front;
|
||||
try {
|
||||
@@ -123,6 +47,71 @@ function buildFedcmEndpointUrls(issuer: string, frontendUrl: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function resolveSameOriginFrontend(storedFrontend: string, req?: Request): string {
|
||||
const fromRequest = resolvePublicFrontendBaseFromRequest(req);
|
||||
const preferred = preferBrowserReachableBase(storedFrontend, fromRequest);
|
||||
if (preferred !== storedFrontend) {
|
||||
return preferred;
|
||||
}
|
||||
|
||||
const host = readRequestHost(req);
|
||||
if (!host) {
|
||||
return storedFrontend;
|
||||
}
|
||||
|
||||
const requestOrigin = normalizePublicBaseUrl(`${readRequestProto(req)}://${host}`);
|
||||
|
||||
try {
|
||||
const frontendUrl = new URL(storedFrontend);
|
||||
const requestUrl = new URL(requestOrigin);
|
||||
|
||||
if (hostsMatch(frontendUrl.hostname, requestUrl.hostname)) {
|
||||
return requestOrigin;
|
||||
}
|
||||
} catch {
|
||||
return storedFrontend;
|
||||
}
|
||||
|
||||
return storedFrontend;
|
||||
}
|
||||
|
||||
export function resolveSameOriginIssuer(storedIssuer: string, storedFrontend: string, req?: Request): string {
|
||||
const fromRequest = resolvePublicApiBaseFromRequest(req);
|
||||
const preferred = preferBrowserReachableBase(storedIssuer, fromRequest);
|
||||
if (preferred !== storedIssuer) {
|
||||
return preferred;
|
||||
}
|
||||
|
||||
const host = readRequestHost(req);
|
||||
if (!host) {
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
const requestOrigin = normalizePublicBaseUrl(`${readRequestProto(req)}://${host}`);
|
||||
const sameOriginApi = `${requestOrigin}/idp-api`;
|
||||
|
||||
try {
|
||||
const issuerUrl = new URL(storedIssuer);
|
||||
const frontendUrl = new URL(storedFrontend);
|
||||
const requestUrl = new URL(requestOrigin);
|
||||
|
||||
const hostMatches =
|
||||
hostsMatch(issuerUrl.hostname, requestUrl.hostname) || hostsMatch(frontendUrl.hostname, requestUrl.hostname);
|
||||
|
||||
if (!hostMatches) {
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
if (normalizePublicBaseUrl(storedIssuer) !== sameOriginApi) {
|
||||
return sameOriginApi;
|
||||
}
|
||||
} catch {
|
||||
return fromRequest ?? storedIssuer;
|
||||
}
|
||||
|
||||
return storedIssuer;
|
||||
}
|
||||
|
||||
export async function resolveFedcmEndpoints(core: CoreGrpcService, req?: Request): Promise<FedcmEndpoints> {
|
||||
const storedIssuer = await resolveOAuthIssuer(core);
|
||||
const storedFrontend = await resolveFrontendUrl(core);
|
||||
|
||||
Reference in New Issue
Block a user