2025-11-07 22:34:54 -08:00
|
|
|
/**
|
|
|
|
|
* OIDC/OAuth2 helpers
|
|
|
|
|
*/
|
|
|
|
|
|
2025-11-10 19:43:02 -08:00
|
|
|
import fetch from 'node-fetch';
|
|
|
|
|
|
2025-11-07 22:34:54 -08:00
|
|
|
export interface OIDCConfig {
|
|
|
|
|
issuer: string;
|
|
|
|
|
clientId: string;
|
|
|
|
|
clientSecret: string;
|
|
|
|
|
redirectUri: string;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-10 19:43:02 -08:00
|
|
|
export interface TokenResponse {
|
|
|
|
|
access_token: string;
|
|
|
|
|
token_type: string;
|
|
|
|
|
expires_in?: number;
|
|
|
|
|
refresh_token?: string;
|
|
|
|
|
id_token?: string;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 22:34:54 -08:00
|
|
|
export class OIDCProvider {
|
|
|
|
|
constructor(private config: OIDCConfig) {}
|
|
|
|
|
|
2025-11-10 19:43:02 -08:00
|
|
|
getAuthorizationUrl(state: string): string {
|
2025-11-07 22:34:54 -08:00
|
|
|
const params = new URLSearchParams({
|
|
|
|
|
client_id: this.config.clientId,
|
|
|
|
|
redirect_uri: this.config.redirectUri,
|
|
|
|
|
response_type: 'code',
|
|
|
|
|
scope: 'openid profile email',
|
|
|
|
|
state,
|
|
|
|
|
});
|
|
|
|
|
return `${this.config.issuer}/authorize?${params.toString()}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async exchangeCodeForToken(code: string): Promise<string> {
|
2025-11-10 19:43:02 -08:00
|
|
|
const tokenEndpoint = `${this.config.issuer}/token`;
|
|
|
|
|
|
|
|
|
|
const params = new URLSearchParams({
|
|
|
|
|
grant_type: 'authorization_code',
|
|
|
|
|
code,
|
|
|
|
|
redirect_uri: this.config.redirectUri,
|
|
|
|
|
client_id: this.config.clientId,
|
|
|
|
|
client_secret: this.config.clientSecret,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const response = await fetch(tokenEndpoint, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
|
|
|
},
|
|
|
|
|
body: params.toString(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
const errorText = await response.text();
|
|
|
|
|
throw new Error(`Token exchange failed: ${response.status} ${errorText}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const tokenData = (await response.json()) as TokenResponse;
|
|
|
|
|
return tokenData.access_token;
|
2025-11-07 22:34:54 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|