[GH-ISSUE #7416] kid not set with jwt plugin and advanced: {database: {generateID: false} #10807

Closed
opened 2026-04-13 07:09:59 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @demhadais on GitHub (Jan 16, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7416

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Using sveltekit, just run:

npm run dev

with the following in src/lib/auth.ts:

import { betterAuth } from "better-auth";
import { sveltekitCookies } from "better-auth/svelte-kit";
import { getRequestEvent } from "$app/server";

export const auth = betterAuth({
    ..., // SSO confiuration without a database (stateless)
    plugins: [jwt(), sveltekitCookies(getRequestEvent)],
    advanced: {
        database: {
            generateId: false
        }
    }
})

Current vs. Expected behavior

Expected behavior

The keys returned by /api/auth/jwks each contain a kid, like this section in the documentation shows.

Current behavior

No kid is set, and the returned token from /api/auth/token does not have a kid in the header either.

/api/auth/jwks

{
  "keys": [
    {
      "alg": "EdDSA",
      "crv": "Ed25519",
      "kty": "OKP",
      "x": "54cXwRZHbDKIYoyjzOeAi0DsUF8Ry5v7RlC1LuLsvL0"
    }
  ]
}

api/auth/token (just the decoded header)

{
  "alg": "EdDSA"
}

What version of Better Auth are you using?

1.4.13

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "unknown",
    "release": "25.2.0",
    "cpuCount": 14,
    "cpuModel": "Apple M4 Pro",
    "totalMemory": "24.00 GB",
    "freeMemory": "0.89 GB"
  },
  "node": {
    "version": "v24.3.0",
    "env": "development"
  },
  "packageManager": {
    "name": "bun",
    "version": "1.3.5"
  },
  "frameworks": [
    {
      "name": "svelte",
      "version": "^5.46.1"
    },
    {
      "name": "@sveltejs/kit",
      "version": "^2.49.2"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "Unknown",
    "config": null,
    "error": "Failed to load Better Auth config"
  }
}

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

Documentation, Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"

export const auth = betterAuth({
  baseURL: "some url",
  secret: "some secret",
  user: {
    additionalFields: {
      userId: { type: "string" },
      is_admin: { type: "boolean" },
      is_biology_staff: { type: "boolean" },
      is_computational_staff: { type: "boolean" },
    },
  },
  session: {
    cookieCache: {
      strategy: "jwt",
      maxAge: 30 * 60, // 30 minutes
    },
  },
  socialProviders: {
    microsoft: {
      clientId: "client ID",
      clientSecret: "client secret",
      tenantId: "tenant ID",
      mapProfileToUser: async (profile) => {
        // some function that gets the additional fields mentioned above
      },
    },
  },
  plugins: [jwt(), sveltekitCookies(getRequestEvent)],
  advanced: {
      database:  {
          generateId: false
      }
  }
});

Additional context

No response

Originally created by @demhadais on GitHub (Jan 16, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7416 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Using sveltekit, just run: ```bash npm run dev ``` with the following in `src/lib/auth.ts`: ```typescript import { betterAuth } from "better-auth"; import { sveltekitCookies } from "better-auth/svelte-kit"; import { getRequestEvent } from "$app/server"; export const auth = betterAuth({ ..., // SSO confiuration without a database (stateless) plugins: [jwt(), sveltekitCookies(getRequestEvent)], advanced: { database: { generateId: false } } }) ``` ### Current vs. Expected behavior # Expected behavior The keys returned by `/api/auth/jwks` each contain a `kid`, like [this section in the documentation](https://www.better-auth.com/docs/plugins/jwt#verifying-the-token) shows. # Current behavior No `kid` is set, and the returned token from `/api/auth/token` does not have a `kid` in the header either. `/api/auth/jwks` ```json { "keys": [ { "alg": "EdDSA", "crv": "Ed25519", "kty": "OKP", "x": "54cXwRZHbDKIYoyjzOeAi0DsUF8Ry5v7RlC1LuLsvL0" } ] } ``` `api/auth/token` (just the decoded header) ```json { "alg": "EdDSA" } ``` ### What version of Better Auth are you using? 1.4.13 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "unknown", "release": "25.2.0", "cpuCount": 14, "cpuModel": "Apple M4 Pro", "totalMemory": "24.00 GB", "freeMemory": "0.89 GB" }, "node": { "version": "v24.3.0", "env": "development" }, "packageManager": { "name": "bun", "version": "1.3.5" }, "frameworks": [ { "name": "svelte", "version": "^5.46.1" }, { "name": "@sveltejs/kit", "version": "^2.49.2" } ], "databases": null, "betterAuth": { "version": "Unknown", "config": null, "error": "Failed to load Better Auth config" } } ``` ### Which area(s) are affected? (Select all that apply) Documentation, Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ baseURL: "some url", secret: "some secret", user: { additionalFields: { userId: { type: "string" }, is_admin: { type: "boolean" }, is_biology_staff: { type: "boolean" }, is_computational_staff: { type: "boolean" }, }, }, session: { cookieCache: { strategy: "jwt", maxAge: 30 * 60, // 30 minutes }, }, socialProviders: { microsoft: { clientId: "client ID", clientSecret: "client secret", tenantId: "tenant ID", mapProfileToUser: async (profile) => { // some function that gets the additional fields mentioned above }, }, }, plugins: [jwt(), sveltekitCookies(getRequestEvent)], advanced: { database: { generateId: false } } }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 07:09:59 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Jan 16, 2026):

It seems that you're experiencing an issue where the kid (key ID) is not being set in your JWT plugin configuration in Better Auth. The kid is typically included in the JWT's header to identify which key was used for signing.

Here are some troubleshooting steps you can take:

  1. Ensure JWT Plugin is Properly Configured: Make sure you have properly included the JWT plugin in your Better Auth configuration. Double-check that the plugin has been installed and is being used in your auth config.

  2. Verify Key Generation: When you set up the JWKS (JSON Web Key Set), ensure it is configured to return keys with an ID. You might need to inspect the logic around key generation to make sure it is correctly assigning a kid to your keys.

  3. Test with Other Configurations: If you have custom logic related to key management, try simplifying it to see if a basic configuration yields the kid. For instance, disable any custom configurations and check if the default setup works.

  4. Check Documentation: Refer to the JWT plugin documentation to ensure all required settings are being used correctly. You will want to validate how to ensure that keys with a kid are returned in your JWKS [1].

If you've gone through these steps and are still having trouble, it could be worthwhile to open an issue on GitHub for more focused support from the developers. In your message, please describe the context and what you’ve already tried, and you might tag Beka or Max (@bekacru or @ping__) for further assistance from the Better Auth team.

Would you like to explore any specific hooks or features of the JWT plugin that might help with your setup?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3760795538 --> @better-auth-agent[bot] commented on GitHub (Jan 16, 2026): It seems that you're experiencing an issue where the `kid` (key ID) is not being set in your JWT plugin configuration in Better Auth. The `kid` is typically included in the JWT's header to identify which key was used for signing. Here are some troubleshooting steps you can take: 1. **Ensure JWT Plugin is Properly Configured**: Make sure you have properly included the JWT plugin in your Better Auth configuration. Double-check that the plugin has been installed and is being used in your auth config. 2. **Verify Key Generation**: When you set up the JWKS (JSON Web Key Set), ensure it is configured to return keys with an ID. You might need to inspect the logic around key generation to make sure it is correctly assigning a `kid` to your keys. 3. **Test with Other Configurations**: If you have custom logic related to key management, try simplifying it to see if a basic configuration yields the `kid`. For instance, disable any custom configurations and check if the default setup works. 4. **Check Documentation**: Refer to the JWT plugin documentation to ensure all required settings are being used correctly. You will want to validate how to ensure that keys with a `kid` are returned in your JWKS [[1]](https://www.better-auth.com/docs/plugins/jwt). If you've gone through these steps and are still having trouble, it could be worthwhile to open an issue on GitHub for more focused support from the developers. In your message, please describe the context and what you’ve already tried, and you might tag Beka or Max (@bekacru or @ping__) for further assistance from the Better Auth team. Would you like to explore any specific hooks or features of the JWT plugin that might help with your setup? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@dosubot[bot] commented on GitHub (Jan 16, 2026):

The JWT plugin in Better Auth is designed to set the kid field in both JWKS keys and JWT headers, using the key's id property from the storage adapter. If you're seeing JWKS keys and JWTs without a kid, it's likely because your stateless setup (no database or custom adapter) is generating keys without an id, so kid is missing in the output. There are no hidden config flags for this—it's tied directly to the key identifier in the storage layer. This can cause issues with token verification in downstream services that expect kid for key selection and rotation.

To fix this, you need to ensure that your key generation logic (or adapter, if you use one) sets a unique id for each key. Using a database-backed adapter or customizing your stateless key generation to include an id will result in JWKS and JWTs with the expected kid field. This is the standard and documented behavior for interoperability and security (source).

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:3760804066 --> @dosubot[bot] commented on GitHub (Jan 16, 2026): <!-- Answer --> The JWT plugin in Better Auth is designed to set the `kid` field in both JWKS keys and JWT headers, using the key's `id` property from the storage adapter. If you're seeing JWKS keys and JWTs without a `kid`, it's likely because your stateless setup (no database or custom adapter) is generating keys without an `id`, so `kid` is missing in the output. There are no hidden config flags for this—it's tied directly to the key identifier in the storage layer. This can cause issues with token verification in downstream services that expect `kid` for key selection and rotation. To fix this, you need to ensure that your key generation logic (or adapter, if you use one) sets a unique `id` for each key. Using a database-backed adapter or customizing your stateless key generation to include an `id` will result in JWKS and JWTs with the expected `kid` field. This is the standard and documented behavior for interoperability and security ([source](https://github.com/better-auth/better-auth/blob/e14c211afdef90ac1b0c328db3471fae4b5a0923/packages/better-auth/src/plugins/jwt/sign.ts#L64-L144)). <!-- 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/9295a40e-b39c-4388-bc3c-be7845a4dda5?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/9295a40e-b39c-4388-bc3c-be7845a4dda5?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/9295a40e-b39c-4388-bc3c-be7845a4dda5?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/9295a40e-b39c-4388-bc3c-be7845a4dda5?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/9295a40e-b39c-4388-bc3c-be7845a4dda5?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/9295a40e-b39c-4388-bc3c-be7845a4dda5?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/9295a40e-b39c-4388-bc3c-be7845a4dda5?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=The%20JWT%20plugin%20in%20Better%20Auth%20is%20designed%20to%20set%20the%20%60kid%60%20field%20in%20both%20JWKS%20keys%20and%20JWT%20headers%2C%20using%20the%20key%27s%20%60id%60%20property%20from%20the%20storage%20adapter.%20If%20you%27re%20seeing%20JWKS%20keys%20and%20JWTs%20without%20a%20%60kid%60%2C%20it%27s%20likely%20because%20your%20stateless%20setup%20%28no%20database%20or%20custom%20adapter%29%20is%20generating%20keys%20without%20an%20%60id%60%2C%20so%20%60kid%60%20is%20missing%20in%20the%20output.%20There%20are%20no%20hidden%20config%20flags%20for%20this%E2%80%94it%27s%20tied%20directly%20to%20the%20key%20identifier%20in%20the%20storage%20layer.%20This%20can%20cause%20issues%20with%20token%20verification%20in%20downstream%20services%20that%20expect%20%60kid%60%20for%20key%20selection%20and%20rotation.%0A%0ATo%20fix%20this%2C%20you%20need%20to%20ensure%20that%20your%20key%20generation%20logic%20%28or%20adapter%2C%20if%20you%20use%20one%29%20sets%20a%20unique%20%60id%60%20for%20each%20key.%20Using%20a%20database-backed%20adapter%20or%20customizing%20your%20stateless%20key%20generation%20to%20include%20an%20%60id%60%20will%20result%20in%20JWKS%20and%20JWTs%20with%20the%20expected%20%60kid%60%20field.%20This%20is%20the%20standard%20and%20documented%20behavior%20for%20interoperability%20and%20security%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/blob/e14c211afdef90ac1b0c328db3471fae4b5a0923/packages/better-auth/src/plugins/jwt/sign.ts%23L64-L144%29%29.)&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/7416)
Author
Owner

@demhadais commented on GitHub (Jan 16, 2026):

I actually just figured this out. I'm closing this and opening another issue about documentation.

<!-- gh-comment-id:3760829059 --> @demhadais commented on GitHub (Jan 16, 2026): I actually just figured this out. I'm closing this and opening another issue about documentation.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10807