monacousa-portal/server/utils/keycloak.ts

84 lines
2.3 KiB
TypeScript

import type { KeycloakConfig, TokenResponse, UserInfo } from '~/utils/types';
export class KeycloakClient {
private config: KeycloakConfig;
constructor(config: KeycloakConfig) {
this.config = config;
}
getAuthUrl(state: string): string {
const params = new URLSearchParams({
client_id: this.config.clientId,
redirect_uri: this.config.callbackUrl,
response_type: 'code',
scope: 'openid email profile',
state,
});
return `${this.config.issuer}/protocol/openid-connect/auth?${params}`;
}
async exchangeCodeForTokens(code: string): Promise<TokenResponse> {
const response = await fetch(`${this.config.issuer}/protocol/openid-connect/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: this.config.clientId,
client_secret: this.config.clientSecret,
code,
redirect_uri: this.config.callbackUrl,
}),
});
if (!response.ok) {
throw new Error(`Token exchange failed: ${response.statusText}`);
}
return response.json();
}
async getUserInfo(accessToken: string): Promise<UserInfo> {
const response = await fetch(`${this.config.issuer}/protocol/openid-connect/userinfo`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to get user info: ${response.statusText}`);
}
return response.json();
}
async refreshToken(refreshToken: string): Promise<TokenResponse> {
const response = await fetch(`${this.config.issuer}/protocol/openid-connect/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: this.config.clientId,
client_secret: this.config.clientSecret,
refresh_token: refreshToken,
}),
});
if (!response.ok) {
throw new Error(`Token refresh failed: ${response.statusText}`);
}
return response.json();
}
}
export function createKeycloakClient(): KeycloakClient {
const config = useRuntimeConfig();
return new KeycloakClient(config.keycloak);
}