Skip to content

Commit 58940f7

Browse files
committed
fix(generic-oauth): use discovery userinfo endpoint instead of hardcoded URLs (#8223)
1 parent 4ac7866 commit 58940f7

File tree

4 files changed

+3
-132
lines changed

4 files changed

+3
-132
lines changed

packages/better-auth/src/plugins/generic-oauth/generic-oauth.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,8 +1045,7 @@ describe("oauth2", async () => {
10451045
expect(oktaConfig.scopes).toEqual(["openid", "profile", "email"]);
10461046
expect(oktaConfig.clientId).toBe("okta-client-id");
10471047
expect(oktaConfig.clientSecret).toBe("okta-client-secret");
1048-
expect(oktaConfig.getUserInfo).toBeDefined();
1049-
expect(typeof oktaConfig.getUserInfo).toBe("function");
1048+
expect(oktaConfig.getUserInfo).toBeUndefined();
10501049
});
10511050

10521051
it("should handle issuer with trailing slash", () => {
@@ -1101,8 +1100,7 @@ describe("oauth2", async () => {
11011100
expect(auth0Config.scopes).toEqual(["openid", "profile", "email"]);
11021101
expect(auth0Config.clientId).toBe("auth0-client-id");
11031102
expect(auth0Config.clientSecret).toBe("auth0-client-secret");
1104-
expect(auth0Config.getUserInfo).toBeDefined();
1105-
expect(typeof auth0Config.getUserInfo).toBe("function");
1103+
expect(auth0Config.getUserInfo).toBeUndefined();
11061104
});
11071105

11081106
it("should handle domain with protocol prefix", () => {
@@ -1267,8 +1265,7 @@ describe("oauth2", async () => {
12671265
expect(keycloakConfig.scopes).toEqual(["openid", "profile", "email"]);
12681266
expect(keycloakConfig.clientId).toBe("keycloak-client-id");
12691267
expect(keycloakConfig.clientSecret).toBe("keycloak-client-secret");
1270-
expect(keycloakConfig.getUserInfo).toBeDefined();
1271-
expect(typeof keycloakConfig.getUserInfo).toBe("function");
1268+
expect(keycloakConfig.getUserInfo).toBeUndefined();
12721269
});
12731270

12741271
it("should handle issuer with trailing slash", () => {
Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { OAuth2Tokens, OAuth2UserInfo } from "@better-auth/core/oauth2";
2-
import { betterFetch } from "@better-fetch/fetch";
31
import type { BaseOAuthProviderOptions, GenericOAuthConfig } from "../index";
42

53
export interface Auth0Options extends BaseOAuthProviderOptions {
@@ -10,17 +8,6 @@ export interface Auth0Options extends BaseOAuthProviderOptions {
108
domain: string;
119
}
1210

13-
interface Auth0Profile {
14-
sub: string;
15-
name?: string;
16-
email?: string;
17-
email_verified?: boolean;
18-
picture?: string;
19-
nickname?: string;
20-
given_name?: string;
21-
family_name?: string;
22-
}
23-
2411
/**
2512
* Auth0 OAuth provider helper
2613
*
@@ -50,33 +37,6 @@ export function auth0(options: Auth0Options): GenericOAuthConfig {
5037
const domain = options.domain.replace(/^https?:\/\//, "");
5138
const discoveryUrl = `https://${domain}/.well-known/openid-configuration`;
5239

53-
const getUserInfo = async (
54-
tokens: OAuth2Tokens,
55-
): Promise<OAuth2UserInfo | null> => {
56-
const userInfoUrl = `https://${domain}/userinfo`;
57-
58-
const { data: profile, error } = await betterFetch<Auth0Profile>(
59-
userInfoUrl,
60-
{
61-
headers: {
62-
Authorization: `Bearer ${tokens.accessToken}`,
63-
},
64-
},
65-
);
66-
67-
if (error || !profile) {
68-
return null;
69-
}
70-
71-
return {
72-
id: profile.sub,
73-
name: profile.name ?? profile.nickname ?? undefined,
74-
email: profile.email ?? undefined,
75-
image: profile.picture,
76-
emailVerified: profile.email_verified ?? false,
77-
};
78-
};
79-
8040
return {
8141
providerId: "auth0",
8242
discoveryUrl,
@@ -88,6 +48,5 @@ export function auth0(options: Auth0Options): GenericOAuthConfig {
8848
disableImplicitSignUp: options.disableImplicitSignUp,
8949
disableSignUp: options.disableSignUp,
9050
overrideUserInfo: options.overrideUserInfo,
91-
getUserInfo,
9251
};
9352
}
Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { OAuth2Tokens, OAuth2UserInfo } from "@better-auth/core/oauth2";
2-
import { betterFetch } from "@better-fetch/fetch";
31
import type { BaseOAuthProviderOptions, GenericOAuthConfig } from "../index";
42

53
export interface KeycloakOptions extends BaseOAuthProviderOptions {
@@ -10,17 +8,6 @@ export interface KeycloakOptions extends BaseOAuthProviderOptions {
108
issuer: string;
119
}
1210

13-
interface KeycloakProfile {
14-
sub: string;
15-
name?: string;
16-
email?: string;
17-
email_verified?: boolean;
18-
picture?: string;
19-
preferred_username?: string;
20-
given_name?: string;
21-
family_name?: string;
22-
}
23-
2411
/**
2512
* Keycloak OAuth provider helper
2613
*
@@ -50,36 +37,6 @@ export function keycloak(options: KeycloakOptions): GenericOAuthConfig {
5037
const issuer = options.issuer.replace(/\/$/, "");
5138
const discoveryUrl = `${issuer}/.well-known/openid-configuration`;
5239

53-
const getUserInfo = async (
54-
tokens: OAuth2Tokens,
55-
): Promise<OAuth2UserInfo | null> => {
56-
// Construct userinfo URL from issuer
57-
const userInfoUrl = `${issuer}/protocol/openid-connect/userinfo`;
58-
59-
const { data: profile, error } = await betterFetch<KeycloakProfile>(
60-
userInfoUrl,
61-
{
62-
headers: {
63-
Authorization: `Bearer ${tokens.accessToken}`,
64-
},
65-
},
66-
);
67-
68-
if (error || !profile) {
69-
return null;
70-
}
71-
72-
return {
73-
id: profile.sub,
74-
name: profile.name ?? profile.preferred_username ?? undefined,
75-
email: profile.email ?? undefined,
76-
image: profile.picture,
77-
// Keycloak provides email_verified per OIDC standard, but availability depends on configuration.
78-
// We default to false when not provided or not configured.
79-
emailVerified: profile.email_verified ?? false,
80-
};
81-
};
82-
8340
return {
8441
providerId: "keycloak",
8542
discoveryUrl,
@@ -91,6 +48,5 @@ export function keycloak(options: KeycloakOptions): GenericOAuthConfig {
9148
disableImplicitSignUp: options.disableImplicitSignUp,
9249
disableSignUp: options.disableSignUp,
9350
overrideUserInfo: options.overrideUserInfo,
94-
getUserInfo,
9551
};
9652
}
Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { OAuth2Tokens, OAuth2UserInfo } from "@better-auth/core/oauth2";
2-
import { betterFetch } from "@better-fetch/fetch";
31
import type { BaseOAuthProviderOptions, GenericOAuthConfig } from "../index";
42

53
export interface OktaOptions extends BaseOAuthProviderOptions {
@@ -10,17 +8,6 @@ export interface OktaOptions extends BaseOAuthProviderOptions {
108
issuer: string;
119
}
1210

13-
interface OktaProfile {
14-
sub: string;
15-
name?: string;
16-
email?: string;
17-
email_verified?: boolean;
18-
picture?: string;
19-
preferred_username?: string;
20-
given_name?: string;
21-
family_name?: string;
22-
}
23-
2411
/**
2512
* Okta OAuth provider helper
2613
*
@@ -50,33 +37,6 @@ export function okta(options: OktaOptions): GenericOAuthConfig {
5037
const issuer = options.issuer.replace(/\/$/, "");
5138
const discoveryUrl = `${issuer}/.well-known/openid-configuration`;
5239

53-
const getUserInfo = async (
54-
tokens: OAuth2Tokens,
55-
): Promise<OAuth2UserInfo | null> => {
56-
const userInfoUrl = `${issuer}/oauth2/v1/userinfo`;
57-
58-
const { data: profile, error } = await betterFetch<OktaProfile>(
59-
userInfoUrl,
60-
{
61-
headers: {
62-
Authorization: `Bearer ${tokens.accessToken}`,
63-
},
64-
},
65-
);
66-
67-
if (error || !profile) {
68-
return null;
69-
}
70-
71-
return {
72-
id: profile.sub,
73-
name: profile.name ?? profile.preferred_username ?? undefined,
74-
email: profile.email ?? undefined,
75-
image: profile.picture,
76-
emailVerified: profile.email_verified ?? false,
77-
};
78-
};
79-
8040
return {
8141
providerId: "okta",
8242
discoveryUrl,
@@ -88,6 +48,5 @@ export function okta(options: OktaOptions): GenericOAuthConfig {
8848
disableImplicitSignUp: options.disableImplicitSignUp,
8949
disableSignUp: options.disableSignUp,
9050
overrideUserInfo: options.overrideUserInfo,
91-
getUserInfo,
9251
};
9352
}

0 commit comments

Comments
 (0)