Files
IdP/apps/frontend/lib/oauth-url.ts
2026-06-29 14:40:35 +03:00

108 lines
3.5 KiB
TypeScript

export function normalizeBaseUrl(url: string) {
return url.trim().replace(/\/+$/, '');
}
export function resolveOAuthApiBase(settings: Record<string, string>, fallback = 'http://localhost:3002/idp-api') {
const publicApi = settings.PUBLIC_API_URL?.trim();
if (publicApi) {
return normalizeBaseUrl(publicApi);
}
const domain = settings.PROJECT_DOMAIN?.trim();
if (domain) {
if (domain.startsWith('http://') || domain.startsWith('https://')) {
return normalizeBaseUrl(domain);
}
return `https://${domain.replace(/^\/+/, '')}/idp-api`;
}
return normalizeBaseUrl(fallback);
}
export function resolveFrontendBase(settings: Record<string, string>, fallback = 'http://localhost:3002') {
const publicFrontend = settings.PUBLIC_FRONTEND_URL?.trim();
if (publicFrontend) {
return normalizeBaseUrl(publicFrontend);
}
const domain = settings.PROJECT_DOMAIN?.trim();
if (domain) {
if (domain.startsWith('http://') || domain.startsWith('https://')) {
return normalizeBaseUrl(domain);
}
return `https://${domain.replace(/^\/+/, '')}`;
}
return normalizeBaseUrl(fallback);
}
export interface OAuthEndpoints {
issuer: string;
authorizationEndpoint: string;
tokenEndpoint: string;
userInfoEndpoint: string;
openIdConfigurationUrl: string;
jwksUrl: string;
webIdentityUrl: string;
fedcmConfigUrl: string;
fedcmDiscoverUrl: string;
fedcmAccountsUrl: string;
fedcmIdAssertionUrl: string;
widgetUrl: string;
}
export function buildOAuthEndpoints(apiBase: string, frontendBase?: string): OAuthEndpoints {
const base = normalizeBaseUrl(apiBase);
const front = normalizeBaseUrl(frontendBase ?? deriveFrontendBaseFromApi(base));
let webIdentityOrigin = front;
try {
webIdentityOrigin = new URL(base).origin;
} catch {
// keep frontend origin
}
return {
issuer: base,
authorizationEndpoint: `${base}/oauth/authorize`,
tokenEndpoint: `${base}/oauth/token`,
userInfoEndpoint: `${base}/oauth/userinfo`,
openIdConfigurationUrl: `${base}/.well-known/openid-configuration`,
jwksUrl: `${base}/.well-known/jwks.json`,
webIdentityUrl: `${webIdentityOrigin}/.well-known/web-identity`,
fedcmConfigUrl: `${base}/fedcm/config.json`,
fedcmDiscoverUrl: `${base}/fedcm/discover.json`,
fedcmAccountsUrl: `${base}/fedcm/accounts`,
fedcmIdAssertionUrl: `${base}/fedcm/id_assertion`,
widgetUrl: `${front}/sso-widget.js`
};
}
function deriveFrontendBaseFromApi(apiBase: string) {
if (apiBase.endsWith('/idp-api')) {
return apiBase.replace(/\/idp-api$/, '');
}
return apiBase;
}
export function buildAuthorizeUrl(
apiBase: string,
params: { clientId: string; redirectUri: string; scope: string; userId?: string; state?: string; useStandardParams?: boolean }
) {
const url = new URL(`${normalizeBaseUrl(apiBase)}/oauth/authorize`);
if (params.useStandardParams ?? true) {
url.searchParams.set('client_id', params.clientId);
url.searchParams.set('redirect_uri', params.redirectUri);
url.searchParams.set('response_type', 'code');
url.searchParams.set('scope', params.scope);
if (params.state) url.searchParams.set('state', params.state);
} else {
url.searchParams.set('clientId', params.clientId);
url.searchParams.set('redirectUri', params.redirectUri);
url.searchParams.set('scope', params.scope);
if (params.userId) url.searchParams.set('userId', params.userId);
if (params.state) url.searchParams.set('state', params.state);
}
return url.toString();
}