Files
IdP/apps/docs/lib/oauth-url.ts
2026-06-25 23:48:57 +03:00

57 lines
1.9 KiB
TypeScript

export function normalizeBaseUrl(url: string) {
return url.trim().replace(/\/+$/, '');
}
export function resolveOAuthApiBase(settings: Record<string, string>, fallback = 'http://localhost:3000') {
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(/^\/+/, '')}`;
}
return normalizeBaseUrl(fallback);
}
export interface OAuthEndpoints {
issuer: string;
authorizationEndpoint: string;
tokenEndpoint: string;
userInfoEndpoint: string;
openIdConfigurationUrl: string;
jwksUrl: string;
}
export function buildOAuthEndpoints(apiBase: string): OAuthEndpoints {
const base = normalizeBaseUrl(apiBase);
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`
};
}
export function buildAuthorizeUrl(
apiBase: string,
params: { clientId: string; redirectUri: string; scope: string; state?: string; codeChallenge?: string; codeChallengeMethod?: string }
) {
const url = new URL(`${normalizeBaseUrl(apiBase)}/oauth/authorize`);
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);
if (params.codeChallenge) url.searchParams.set('code_challenge', params.codeChallenge);
if (params.codeChallengeMethod) url.searchParams.set('code_challenge_method', params.codeChallengeMethod);
return url.toString();
}