diff --git a/lib/keycloak.ts b/lib/keycloak.ts index ee5e65f4..00feb3e7 100644 --- a/lib/keycloak.ts +++ b/lib/keycloak.ts @@ -53,37 +53,51 @@ export async function getKeycloakAdminClient(): Promise { console.log(`Connecting to Keycloak at ${keycloakUrl}, realm: ${realmName}, client: ${clientId}`); try { - // Create and configure the admin client + // Create and configure the admin client - we have already validated realmName is defined above const kcAdminClient = new KcAdminClient({ baseUrl: keycloakUrl, - realmName: 'master', // Start with master realm for auth + realmName: realmName!, // Non-null assertion since we validated above }); - // Try client credentials first if available (preferred method) + // Try to authenticate directly with a token from the token endpoint + console.log('Authenticating with direct token fetch'); + + const tokenUrl = `${keycloakUrl}/realms/${realmName}/protocol/openid-connect/token`; + const formData = new URLSearchParams(); + + // clientId is validated above, so it's safe to use non-null assertion + formData.append('client_id', clientId!); + if (clientSecret) { - console.log('Authenticating with client credentials'); - await kcAdminClient.auth({ - clientId, - clientSecret, - grantType: 'client_credentials', - }); - } - // Fall back to password grant - else if (adminUsername && adminPassword) { - console.log('Authenticating with password grant'); - await kcAdminClient.auth({ - clientId, - username: adminUsername, - password: adminPassword, - grantType: 'password', - }); + formData.append('client_secret', clientSecret); + formData.append('grant_type', 'client_credentials'); + } else if (adminUsername && adminPassword) { + formData.append('username', adminUsername); + formData.append('password', adminPassword); + formData.append('grant_type', 'password'); + } else { + // This should never happen due to validation above + throw new Error('No valid authentication method available'); } - - // Now that we're authenticated, set the target realm - kcAdminClient.setConfig({ - realmName, + + const response = await fetch(tokenUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: formData, }); - + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(`Authentication failed: ${errorData.error || response.statusText}`); + } + + const tokenData = await response.json(); + + // Set the token manually + kcAdminClient.setAccessToken(tokenData.access_token); + // Test that authentication worked with a simple request await kcAdminClient.users.find({ max: 1 });