[GH-ISSUE #8269] [BUG] SSO module looking for non-existent ID claim #28362

Closed
opened 2026-04-17 19:47:29 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @steveiliop56 on GitHub (Mar 1, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8269

Originally assigned to: @Paola3stefania on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Using an OIDC server like Tinyauth (which does not include the user-info claims in the ID token), set-up a demo application with SSO and try to login. You will be greeted with the error=invalid_provider&error_description=missing_user_info error.

Current vs. Expected behavior

Looking through the code, specifically here:

425c6abf6e/packages/sso/src/routes/sso.ts (L1714-L1720)

Seems like better-auth is trying to extract some id claim from the user-info endpoint. However, according to Section 5.1 of the OIDC specification, the OIDC server is not obligated to return such claim. Normally, better-auth should be looking for the sub claim (containing the ID of the user that remains static despite of profile changes) instead of an id one.

I am guessing that since most OIDC providers include the claims in the ID token (which is not required according to Section 2), the user-info extraction logic from the ID token happens first and thus there is no need to check the user-info endpoint which would most likely fail.

What version of Better Auth are you using?

1.5.0

System info

Not relevant to the issue.

Which area(s) are affected? (Select all that apply)

Client

Auth config (if applicable)

Not applicable.

Additional context

No response

Originally created by @steveiliop56 on GitHub (Mar 1, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8269 Originally assigned to: @Paola3stefania on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Using an OIDC server like [Tinyauth](https://github.com/steveiliop56/tinyauth) (which does not include the user-info claims in the ID token), set-up a demo application with SSO and try to login. You will be greeted with the `error=invalid_provider&error_description=missing_user_info` error. ### Current vs. Expected behavior Looking through the code, specifically here: https://github.com/better-auth/better-auth/blob/425c6abf6eb703ad6a77d5b9dd663e24fa2027d5/packages/sso/src/routes/sso.ts#L1714-L1720 Seems like better-auth is trying to extract some `id` claim from the user-info endpoint. However, according to [Section 5.1](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) of the OIDC specification, the OIDC server is not obligated to return such claim. Normally, better-auth should be looking for the `sub` claim (containing the ID of the user that remains static despite of profile changes) instead of an `id` one. I am guessing that since most OIDC providers include the claims in the ID token (which is not required according to [Section 2](https://openid.net/specs/openid-connect-core-1_0.html#IDToken)), the user-info extraction logic from the ID token happens first and thus there is no need to check the user-info endpoint which would most likely fail. ### What version of Better Auth are you using? 1.5.0 ### System info ```bash Not relevant to the issue. ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript Not applicable. ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-17 19:47:29 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Mar 1, 2026):

Hi @steveiliop56! I'm Dosu and I’m helping the better-auth team.

Your analysis is correct - this is a valid OIDC compliance bug. The issue is that Better Auth handles ID tokens and UserInfo endpoint responses inconsistently:

ID Token path (working correctly): Uses sub claim by default with configurable mapping:

id: idToken[mapping.id || "sub"],  // ✅ Correctly uses 'sub'

UserInfo endpoint path (the bug): Directly assigns the response without any mapping, then checks for userInfo.id which doesn't exist in standard OIDC responses that return sub.

Workaround: You can override getUserInfo in your provider configuration to map sub to id:

getUserInfo: async (token) => {
  const response = await fetch(providerConfig.userInfoEndpoint, {
    headers: { Authorization: `Bearer ${token.accessToken}` }
  });
  const data = await response.json();
  
  return {
    user: {
      id: data.sub,  // Map 'sub' to 'id'
      email: data.email,
      name: data.name,
      image: data.picture,
      emailVerified: data.email_verified ?? false,
    },
    data,
  };
}

Alternatively, if you can configure Tinyauth to include all claims in the ID token itself, Better Auth will use the ID token path (which handles sub correctly) and avoid this bug entirely.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3981102489 --> @dosubot[bot] commented on GitHub (Mar 1, 2026): <!-- Greeting --> Hi @steveiliop56! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Your analysis is correct - this is a valid OIDC compliance bug. The issue is that Better Auth handles ID tokens and UserInfo endpoint responses inconsistently: **ID Token path** (working correctly): Uses `sub` claim by default with [configurable mapping](https://github.com/better-auth/better-auth/blob/ffa72e11dc8ef4f9177a91a404ac5d276bdc8d4b/packages/sso/src/routes/sso.ts#L1661-L1682): ```typescript id: idToken[mapping.id || "sub"], // ✅ Correctly uses 'sub' ``` **UserInfo endpoint path** (the bug): [Directly assigns the response without any mapping](https://github.com/better-auth/better-auth/blob/ffa72e11dc8ef4f9177a91a404ac5d276bdc8d4b/packages/sso/src/routes/sso.ts#L1711), then [checks for `userInfo.id`](https://github.com/better-auth/better-auth/blob/ffa72e11dc8ef4f9177a91a404ac5d276bdc8d4b/packages/sso/src/routes/sso.ts#L1714-L1720) which doesn't exist in standard OIDC responses that return `sub`. **Workaround**: You can override `getUserInfo` in your provider configuration to map `sub` to `id`: ```typescript getUserInfo: async (token) => { const response = await fetch(providerConfig.userInfoEndpoint, { headers: { Authorization: `Bearer ${token.accessToken}` } }); const data = await response.json(); return { user: { id: data.sub, // Map 'sub' to 'id' email: data.email, name: data.name, image: data.picture, emailVerified: data.email_verified ?? false, }, data, }; } ``` Alternatively, if you can configure Tinyauth to include all claims in the ID token itself, Better Auth will use the ID token path (which handles `sub` correctly) and avoid this bug entirely. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/8ad1b021-2f90-42ca-a3f7-f03447bdc131?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Your%20analysis%20is%20correct%20-%20this%20is%20a%20valid%20OIDC%20compliance%20bug.%20The%20issue%20is%20that%20Better%20Auth%20handles%20ID%20tokens%20and%20UserInfo%20endpoint%20responses%20inconsistently%3A%0A%0A%2A%2AID%20Token%20path%2A%2A%20%28working%20correctly%29%3A%20Uses%20%60sub%60%20claim%20by%20default%20with%20%5Bconfigurable%20mapping%5D%28https%3A//github.com/better-auth/better-auth/blob/ffa72e11dc8ef4f9177a91a404ac5d276bdc8d4b/packages/sso/src/routes/sso.ts%23L1661-L1682%29%3A%0A%60%60%60typescript%0Aid%3A%20idToken%5Bmapping.id%20%7C%7C%20%22sub%22%5D%2C%20%20//%20%E2%9C%85%20Correctly%20uses%20%27sub%27%0A%60%60%60%0A%0A%2A%2AUserInfo%20endpoint%20path%2A%2A%20%28the%20bug%29%3A%20%5BDirectly%20assigns%20the%20response%20without%20any%20mapping%5D%28https%3A//github.com/better-auth/better-auth/blob/ffa72e11dc8ef4f9177a91a404ac5d276bdc8d4b/packages/sso/src/routes/sso.ts%23L1711%29%2C%20then%20%5Bchecks%20for%20%60userInfo.id%60%5D%28https%3A//github.com/better-auth/better-auth/blob/ffa72e11dc8ef4f9177a91a404ac5d276bdc8d4b/packages/sso/src/routes/sso.ts%23L1714-L1720%29%20which%20doesn%27t%20exist%20in%20standard%20OIDC%20responses%20that%20return%20%60sub%60.%0A%0A%2A%2AWorkaround%2A%2A%3A%20You%20can%20override%20%60getUserInfo%60%20in%20your%20provider%20configuration%20to%20map%20%60sub%60%20to%20%60id%60%3A%0A%0A%60%60%60typescript%0AgetUserInfo%3A%20async%20%28token%29%20%3D%3E%20%7B%0A%20%20const%20response%20%3D%20await%20fetch%28providerConfig.userInfoEndpoint%2C%20%7B%0A%20%20%20%20headers%3A%20%7B%20Authorization%3A%20%60Bearer%20%24%7Btoken.accessToken%7D%60%20%7D%0A%20%20%7D%29%3B%0A%20%20const%20data%20%3D%20await%20response.json%28%29%3B%0A%20%20%0A%20%20return%20%7B%0A%20%20%20%20user%3A%20%7B%0A%20%20%20%20%20%20id%3A%20data.sub%2C%20%20//%20Map%20%27sub%27%20to%20%27id%27%0A%20%20%20%20%20%20email%3A%20data.email%2C%0A%20%20%20%20%20%20name%3A%20data.name%2C%0A%20%20%20%20%20%20image%3A%20data.picture%2C%0A%20%20%20%20%20%20emailVerified%3A%20data.email_verified%20%3F%3F%20false%2C%0A%20%20%20%20%7D%2C%0A%20%20%20%20data%2C%0A%20%20%7D%3B%0A%7D%0A%60%60%60%0A%0AAlternatively%2C%20if%20you%20can%20configure%20Tinyauth%20to%20include%20all%20claims%20in%20the%20ID%20token%20itself%2C%20Better%20Auth%20will%20use%20the%20ID%20token%20path%20%28which%20handles%20%60sub%60%20correctly%29%20and%20avoid%20this%20bug%20entirely.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/8269)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28362