[GH-ISSUE #5169] OIDC value not showing up for SSO registration #18810

Closed
opened 2026-04-15 17:29:22 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @calebcav on GitHub (Oct 8, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5169

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Image

When trying to register SSO OIDC config, the oidcConfig value isn't presented. I was following the documentation that is presented here.

Current vs. Expected behavior

Current Behavior:
Image

Expected:

import { authClient } from "@/lib/auth-client";

// Register with OIDC configuration
await authClient.sso.register({
    providerId: "example-provider",
    issuer: "https://idp.example.com",
    domain: "example.com",
    oidcConfig: {
        clientId: "client-id",
        clientSecret: "client-secret",
        authorizationEndpoint: "https://idp.example.com/authorize",
        tokenEndpoint: "https://idp.example.com/token",
        jwksEndpoint: "https://idp.example.com/jwks",
        discoveryEndpoint: "https://idp.example.com/.well-known/openid-configuration",
        scopes: ["openid", "email", "profile"],
        pkce: true,
        mapping: {
            id: "sub",
            email: "email",
            emailVerified: "email_verified",
            name: "name",
            image: "picture",
            extraFields: {
                department: "department",
                role: "role"
            }
        }
    }
});

What version of Better Auth are you using?

1.3.7

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:50 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6030",
    "release": "25.0.0",
    "cpuCount": 12,
    "cpuModel": "Apple M3 Pro",
    "totalMemory": "18.00 GB",
    "freeMemory": "0.14 GB"
  },
  "node": {
    "version": "v22.13.1",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.5.2"
  },
  "frameworks": [
    {
      "name": "next",
      "version": "15.3.4"
    },
    {
      "name": "react",
      "version": "^19.0.0"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.16.3"
    },
    {
      "name": "@prisma/client",
      "version": "^6.11.0"
    }
  ],
  "betterAuth": {
    "version": "^1.3.27",
    "config": {
      "baseURL": "http://localhost:3000",
      "secret": "[REDACTED]",
      "plugins": [
        {
          "name": "sso",
          "config": {
            "id": "sso",
            "endpoints": {},
            "schema": {
              "ssoProvider": {
                "fields": {
                  "issuer": {
                    "type": "string",
                    "required": true
                  },
                  "oidcConfig": {
                    "type": "string",
                    "required": false
                  },
                  "samlConfig": {
                    "type": "string",
                    "required": false
                  },
                  "userId": {
                    "type": "string",
                    "required": false,
                    "references": {
                      "model": "user",
                      "field": "id",
                      "onDelete": "set null"
                    }
                  },
                  "providerId": {
                    "type": "string",
                    "required": true,
                    "unique": true
                  },
                  "organizationId": {
                    "type": "string",
                    "required": false
                  },
                  "domain": {
                    "type": "string",
                    "required": true
                  }
                }
              }
            }
          }
        },
        {
          "name": "custom-session",
          "config": {
            "id": "custom-session",
            "hooks": {
              "after": [
                {}
              ]
            },
            "endpoints": {}
          }
        }
      ],
      "user": {
        "additionalFields": {
          "aaId": {
            "type": "string",
            "required": true,
            "defaultValue": "blank",
            "input": false
          }
        }
      },
      "session": {
        "expiresIn": 3600,
        "updateAge": 86400,
        "cookieCache": {
          "enabled": true,
          "maxAge": 300
        },
        "freshAge": 300
      }
    }
  }
}

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

Documentation, Client, Types, Package

Auth config (if applicable)

export const auth = betterAuth({
  baseURL: process.env.BETTER_AUTH_URL,
  secret: process.env.BETTER_AUTH_SECRET,
  database: prismaAdapter(prisma, {
    provider: "postgresql",
  }),
  plugins: [
    sso(),
    customSession(async ({ user, session }) => {
      return {
        user,
        session: {
          ...session,
          githubToken: null,
        },
      };
    }),
  ],
  user: {
    additionalFields: {
      aaId: {
        type: "string",
        required: true,
        defaultValue: "blank",
        input: false,
      },
    },
  },
  session: {
    expiresIn: 60 * 60, // 1 hour
    updateAge: 60 * 60 * 24, // 24 hours (when to extend the session)
    cookieCache: {
      enabled: true,
      maxAge: 5 * 60,
    },
    freshAge: 60 * 5,
  },
});

Additional context

No response

Originally created by @calebcav on GitHub (Oct 8, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5169 ### Is this suited for github? - [ ] Yes, this is suited for github ### To Reproduce <img width="506" height="234" alt="Image" src="https://github.com/user-attachments/assets/a64057ab-a095-4ace-a1d6-945a112d940e" /> When trying to register SSO OIDC config, the `oidcConfig` value isn't presented. I was following the documentation that is presented [here](https://www.better-auth.com/docs/plugins/sso#register-an-oidc-provider). ### Current vs. Expected behavior Current Behavior: <img width="506" height="234" alt="Image" src="https://github.com/user-attachments/assets/a64057ab-a095-4ace-a1d6-945a112d940e" /> Expected: ``` import { authClient } from "@/lib/auth-client"; // Register with OIDC configuration await authClient.sso.register({ providerId: "example-provider", issuer: "https://idp.example.com", domain: "example.com", oidcConfig: { clientId: "client-id", clientSecret: "client-secret", authorizationEndpoint: "https://idp.example.com/authorize", tokenEndpoint: "https://idp.example.com/token", jwksEndpoint: "https://idp.example.com/jwks", discoveryEndpoint: "https://idp.example.com/.well-known/openid-configuration", scopes: ["openid", "email", "profile"], pkce: true, mapping: { id: "sub", email: "email", emailVerified: "email_verified", name: "name", image: "picture", extraFields: { department: "department", role: "role" } } } }); ``` ### What version of Better Auth are you using? 1.3.7 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.0.0: Wed Sep 17 21:41:50 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6030", "release": "25.0.0", "cpuCount": 12, "cpuModel": "Apple M3 Pro", "totalMemory": "18.00 GB", "freeMemory": "0.14 GB" }, "node": { "version": "v22.13.1", "env": "development" }, "packageManager": { "name": "npm", "version": "11.5.2" }, "frameworks": [ { "name": "next", "version": "15.3.4" }, { "name": "react", "version": "^19.0.0" } ], "databases": [ { "name": "pg", "version": "^8.16.3" }, { "name": "@prisma/client", "version": "^6.11.0" } ], "betterAuth": { "version": "^1.3.27", "config": { "baseURL": "http://localhost:3000", "secret": "[REDACTED]", "plugins": [ { "name": "sso", "config": { "id": "sso", "endpoints": {}, "schema": { "ssoProvider": { "fields": { "issuer": { "type": "string", "required": true }, "oidcConfig": { "type": "string", "required": false }, "samlConfig": { "type": "string", "required": false }, "userId": { "type": "string", "required": false, "references": { "model": "user", "field": "id", "onDelete": "set null" } }, "providerId": { "type": "string", "required": true, "unique": true }, "organizationId": { "type": "string", "required": false }, "domain": { "type": "string", "required": true } } } } } }, { "name": "custom-session", "config": { "id": "custom-session", "hooks": { "after": [ {} ] }, "endpoints": {} } } ], "user": { "additionalFields": { "aaId": { "type": "string", "required": true, "defaultValue": "blank", "input": false } } }, "session": { "expiresIn": 3600, "updateAge": 86400, "cookieCache": { "enabled": true, "maxAge": 300 }, "freshAge": 300 } } } } ``` ### Which area(s) are affected? (Select all that apply) Documentation, Client, Types, Package ### Auth config (if applicable) ```typescript export const auth = betterAuth({ baseURL: process.env.BETTER_AUTH_URL, secret: process.env.BETTER_AUTH_SECRET, database: prismaAdapter(prisma, { provider: "postgresql", }), plugins: [ sso(), customSession(async ({ user, session }) => { return { user, session: { ...session, githubToken: null, }, }; }), ], user: { additionalFields: { aaId: { type: "string", required: true, defaultValue: "blank", input: false, }, }, }, session: { expiresIn: 60 * 60, // 1 hour updateAge: 60 * 60 * 24, // 24 hours (when to extend the session) cookieCache: { enabled: true, maxAge: 5 * 60, }, freshAge: 60 * 5, }, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-15 17:29:22 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Oct 8, 2025):

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

The reason oidcConfig isn't showing up as expected is due to a mismatch between the documentation and the actual implementation. The SSO registration endpoint expects OIDC config fields (like clientId, clientSecret, authorizationEndpoint, etc.) as top-level properties in the request—not nested inside an oidcConfig object. When you pass an oidcConfig object, it gets ignored or isn't processed correctly.

To fix this, spread the OIDC config fields directly into the registration call, like this:

await authClient.sso.register({
  providerId: "example-provider",
  issuer: "https://idp.example.com",
  domain: "example.com",
  clientId: "client-id",
  clientSecret: "client-secret",
  authorizationEndpoint: "https://idp.example.com/authorize",
  tokenEndpoint: "https://idp.example.com/token",
  jwksEndpoint: "https://idp.example.com/jwks",
  discoveryEndpoint: "https://idp.example.com/.well-known/openid-configuration",
  scopes: ["openid", "email", "profile"],
  pkce: true,
  mapping: {
    id: "sub",
    email: "email",
    emailVerified: "email_verified",
    name: "name",
    image: "picture",
    extraFields: {
      department: "department",
      role: "role"
    }
  }
});

The backend will serialize these fields into the oidcConfig string for storage and return them as an object in the response. If you want to see the stored config, check the oidcConfig field in the returned provider object—it will be parsed for you. This behavior is by design in the current version and matches the codebase implementation see source.

If you need to store additional metadata from the OIDC discovery endpoint, you'll need to fetch and include those fields manually at registration time, as the registration process does not fetch or persist them automatically see discussion.

There is also a known issue where the schema expects oidcConfig as a string, so passing an object directly (without proper serialization) can cause JSON parsing errors in some versions see issue. Always follow the top-level field approach for compatibility.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3382877952 --> @dosubot[bot] commented on GitHub (Oct 8, 2025): <!-- Greeting --> Hi @calebcav! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The reason `oidcConfig` isn't showing up as expected is due to a mismatch between the documentation and the actual implementation. The SSO registration endpoint expects OIDC config fields (like `clientId`, `clientSecret`, `authorizationEndpoint`, etc.) as top-level properties in the request—not nested inside an `oidcConfig` object. When you pass an `oidcConfig` object, it gets ignored or isn't processed correctly. To fix this, spread the OIDC config fields directly into the registration call, like this: ```js await authClient.sso.register({ providerId: "example-provider", issuer: "https://idp.example.com", domain: "example.com", clientId: "client-id", clientSecret: "client-secret", authorizationEndpoint: "https://idp.example.com/authorize", tokenEndpoint: "https://idp.example.com/token", jwksEndpoint: "https://idp.example.com/jwks", discoveryEndpoint: "https://idp.example.com/.well-known/openid-configuration", scopes: ["openid", "email", "profile"], pkce: true, mapping: { id: "sub", email: "email", emailVerified: "email_verified", name: "name", image: "picture", extraFields: { department: "department", role: "role" } } }); ``` The backend will serialize these fields into the `oidcConfig` string for storage and return them as an object in the response. If you want to see the stored config, check the `oidcConfig` field in the returned provider object—it will be parsed for you. This behavior is by design in the current version and matches the codebase implementation [see source](https://github.com/better-auth/better-auth/blob/9b1c5d885d16c5101c089f09cce13f1da64dac0b/packages/better-auth/src/plugins/sso/index.ts). If you need to store additional metadata from the OIDC discovery endpoint, you'll need to fetch and include those fields manually at registration time, as the registration process does not fetch or persist them automatically [see discussion](https://github.com/better-auth/better-auth/issues/3728). There is also a known issue where the schema expects `oidcConfig` as a string, so passing an object directly (without proper serialization) can cause JSON parsing errors in some versions [see issue](https://github.com/better-auth/better-auth/issues/4862#issuecomment-3325812803). Always follow the top-level field approach for compatibility. <!-- 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/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/3c1bba92-eff1-4798-a08e-972606c131e9?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&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/5169)
Author
Owner

@Fruup commented on GitHub (Oct 13, 2025):

@calebcav I'm also dealing with this issue. I see two solutions at the moment:

  1. Set the SSO provider in the backend inside the defaultSSO option of the sso plugin (the nested oidcConfig property is expected there)
  2. Register the provider using authClient.sso.register like you do but ignore the TypeScript error using @ts-expect-error. The provider is created correctly despite TypeScript being unhappy.
<!-- gh-comment-id:3397731909 --> @Fruup commented on GitHub (Oct 13, 2025): @calebcav I'm also dealing with this issue. I see two solutions at the moment: 1. Set the SSO provider in the backend inside the `defaultSSO` option of the `sso` plugin (the nested `oidcConfig` property is expected there) 2. Register the provider using `authClient.sso.register` like you do but ignore the TypeScript error using `@ts-expect-error`. The provider is created correctly despite TypeScript being unhappy.
Author
Owner

@Kinfe123 commented on GitHub (Oct 14, 2025):

what version of @better-auth/sso are you using ? try updating to latest version.

<!-- gh-comment-id:3401988670 --> @Kinfe123 commented on GitHub (Oct 14, 2025): what version of `@better-auth/sso` are you using ? try updating to latest version.
Author
Owner

@calebcav commented on GitHub (Oct 14, 2025):

what version of @better-auth/sso are you using ? try updating to latest version.

I am on the latest version

<!-- gh-comment-id:3402750000 --> @calebcav commented on GitHub (Oct 14, 2025): > what version of `@better-auth/sso` are you using ? try updating to latest version. I am on the latest version
Author
Owner

@Kinfe123 commented on GitHub (Oct 14, 2025):

where are you importing the client for ssoClient ?
make sure to import if from @better-auth/sso/client

<!-- gh-comment-id:3403152738 --> @Kinfe123 commented on GitHub (Oct 14, 2025): where are you importing the client for ssoClient ? make sure to import if from `@better-auth/sso/client`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18810