mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-10 04:19:32 +00:00
feat(oidc-provider): add client to getAdditionalUserInfoClaim callback (#3790)
* feat: add oidc Client to getAdditionalUserInfoClaim * address cubic comments * run format
This commit is contained in:
@@ -246,7 +246,7 @@ The UserInfo endpoint returns different claims based on the scopes that were gra
|
||||
- With `profile` scope: Returns name, picture, given_name, family_name
|
||||
- With `email` scope: Returns email and email_verified
|
||||
|
||||
The `getAdditionalUserInfoClaim` function receives the user object and the requested scopes array, allowing you to conditionally include claims based on the scopes granted during authorization. These additional claims will be included in both the UserInfo endpoint response and the ID token.
|
||||
The `getAdditionalUserInfoClaim` function receives the user object, requested scopes array, and the client, allowing you to conditionally include claims based on the scopes granted during authorization. These additional claims will be included in both the UserInfo endpoint response and the ID token.
|
||||
|
||||
### Consent Screen
|
||||
|
||||
@@ -561,6 +561,6 @@ Table Name: `oauthConsent`
|
||||
|
||||
**trustedClients**: `(Client & { skipConsent?: boolean })[]` - Array of trusted clients that are configured directly in the provider options. These clients bypass database lookups and can optionally skip consent screens.
|
||||
|
||||
**getAdditionalUserInfoClaim**: `(user: User, scopes: string[]) => Record<string, any>` - Function to get additional user info claims.
|
||||
**getAdditionalUserInfoClaim**: `(user: User, scopes: string[], client: Client) => Record<string, any>` - Function to get additional user info claims.
|
||||
|
||||
**useJWTPlugin**: `boolean` - When `true`, ID tokens are signed using the JWT plugin's asymmetric keys. When `false` (default), ID tokens are signed with HMAC-SHA256 using the application secret.
|
||||
@@ -570,7 +570,11 @@ export const mcp = (options: MCPOptions) => {
|
||||
};
|
||||
|
||||
const additionalUserClaims = opts.getAdditionalUserInfoClaim
|
||||
? opts.getAdditionalUserInfoClaim(user, requestedScopes)
|
||||
? await opts.getAdditionalUserInfoClaim(
|
||||
user,
|
||||
requestedScopes,
|
||||
client,
|
||||
)
|
||||
: {};
|
||||
|
||||
const idToken = await new SignJWT({
|
||||
|
||||
@@ -31,7 +31,7 @@ describe("mcp", async () => {
|
||||
loginPage: "/login",
|
||||
requirePKCE: true,
|
||||
|
||||
getAdditionalUserInfoClaim(user, scopes) {
|
||||
getAdditionalUserInfoClaim(user, scopes, client) {
|
||||
return {
|
||||
custom: "custom value",
|
||||
userId: user.id,
|
||||
|
||||
@@ -754,7 +754,11 @@ export const oidcProvider = (options: OIDCOptions) => {
|
||||
};
|
||||
|
||||
const additionalUserClaims = options.getAdditionalUserInfoClaim
|
||||
? await options.getAdditionalUserInfoClaim(user, requestedScopes)
|
||||
? await options.getAdditionalUserInfoClaim(
|
||||
user,
|
||||
requestedScopes,
|
||||
client,
|
||||
)
|
||||
: {};
|
||||
|
||||
const payload = {
|
||||
@@ -958,6 +962,18 @@ export const oidcProvider = (options: OIDCOptions) => {
|
||||
});
|
||||
}
|
||||
|
||||
const client = await getClient(
|
||||
accessToken.clientId,
|
||||
ctx.context.adapter,
|
||||
trustedClients,
|
||||
);
|
||||
if (!client) {
|
||||
throw new APIError("UNAUTHORIZED", {
|
||||
error_description: "client not found",
|
||||
error: "invalid_token",
|
||||
});
|
||||
}
|
||||
|
||||
const user = await ctx.context.internalAdapter.findUserById(
|
||||
accessToken.userId,
|
||||
);
|
||||
@@ -986,7 +1002,11 @@ export const oidcProvider = (options: OIDCOptions) => {
|
||||
: undefined,
|
||||
};
|
||||
const userClaims = options.getAdditionalUserInfoClaim
|
||||
? await options.getAdditionalUserInfoClaim(user, requestedScopes)
|
||||
? await options.getAdditionalUserInfoClaim(
|
||||
user,
|
||||
requestedScopes,
|
||||
client,
|
||||
)
|
||||
: baseUserClaims;
|
||||
return ctx.json({
|
||||
...baseUserClaims,
|
||||
|
||||
@@ -32,7 +32,7 @@ describe("oidc", async () => {
|
||||
loginPage: "/login",
|
||||
consentPage: "/oauth2/authorize",
|
||||
requirePKCE: true,
|
||||
getAdditionalUserInfoClaim(user, scopes) {
|
||||
getAdditionalUserInfoClaim(user, scopes, client) {
|
||||
return {
|
||||
custom: "custom value",
|
||||
userId: user.id,
|
||||
@@ -376,7 +376,7 @@ describe("oidc storage", async () => {
|
||||
loginPage: "/login",
|
||||
consentPage: "/oauth2/authorize",
|
||||
requirePKCE: true,
|
||||
getAdditionalUserInfoClaim(user, scopes) {
|
||||
getAdditionalUserInfoClaim(user, scopes, client) {
|
||||
return {
|
||||
custom: "custom value",
|
||||
userId: user.id,
|
||||
@@ -535,7 +535,7 @@ describe("oidc-jwt", async () => {
|
||||
loginPage: "/login",
|
||||
consentPage: "/oauth2/authorize",
|
||||
requirePKCE: true,
|
||||
getAdditionalUserInfoClaim(user, scopes) {
|
||||
getAdditionalUserInfoClaim(user, scopes, client) {
|
||||
return {
|
||||
custom: "custom value",
|
||||
userId: user.id,
|
||||
|
||||
@@ -115,11 +115,13 @@ export interface OIDCOptions {
|
||||
*
|
||||
* @param user - The user object.
|
||||
* @param scopes - The scopes that the client requested.
|
||||
* @param client - The client object.
|
||||
* @returns The user info claim.
|
||||
*/
|
||||
getAdditionalUserInfoClaim?: (
|
||||
user: User & Record<string, any>,
|
||||
scopes: string[],
|
||||
client: Client,
|
||||
) => Record<string, any> | Promise<Record<string, any>>;
|
||||
/**
|
||||
* Trusted clients that are configured directly in the provider options.
|
||||
|
||||
Reference in New Issue
Block a user