[GH-ISSUE #7245] Allow HS256 JWTs #10769

Open
opened 2026-04-13 07:06:45 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @rjungbeck on GitHub (Jan 10, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7245

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Try to create HS256 signed JWTs by specifying
{ secret: "dsafjlkbsflkjsjblfblkfdnöfdnböfdnvbköfdnglödkng",
plugins: [
jwt({jwt: {alg: "HS256})
}

Current vs. Expected behavior

I was not able to convince betterauth to create HS256 signed JWT). It always creates an EdDSA signed JWT token. (I want a symmetric key signed jwt token that I can give to my Python backend). I tried everything differend Gemini, and Pycharms AI suggested (like clearing jwkw table, not providing the table, setting session/strategy=database, jwt/define/algirithm, jwt/signingAlgorithm, jwt/alg)

What version of Better Auth are you using?

1.4.10

System info

Windows 11

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @rjungbeck on GitHub (Jan 10, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7245 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Try to create HS256 signed JWTs by specifying { secret: "dsafjlkbsflkjsjblfblkfdnöfdnböfdnvbköfdnglödkng", plugins: [ jwt({jwt: {alg: "HS256}) } ### Current vs. Expected behavior I was not able to convince betterauth to create HS256 signed JWT). It always creates an EdDSA signed JWT token. (I want a symmetric key signed jwt token that I can give to my Python backend). I tried everything differend Gemini, and Pycharms AI suggested (like clearing jwkw table, not providing the table, setting session/strategy=database, jwt/define/algirithm, jwt/signingAlgorithm, jwt/alg) ### What version of Better Auth are you using? 1.4.10 ### System info ```bash Windows 11 ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the core label 2026-04-13 07:06:45 -05:00
Author
Owner

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

It seems you're encountering issues with getting Better Auth to create HS256 signed JWTs instead of EdDSA signed JWTs. While Better Auth does support HS256, the current implementation might have limitations. There are discussions about the support for HS256 in relation to OIDC.

You'll want to ensure that you are using the JWT plugin correctly in your configuration [1], and if you're following the correct protocol for generating your desired token type. However, based on the information, you might need to check for any specific flags or configurations that allow you to generate HS256 tokens instead of the default EdDSA signatures.

If you haven’t already, I recommend trying the following:

  • Confirm that you have set up the JWT plugin correctly in your auth configuration and specified HS256 as the algorithm.
  • Keep an eye on the latest updates or issues in the Better Auth GitHub repository, as this could provide insights into similar situations faced by other developers.

If you're still having issues, consider tagging Beka and Max (@bekacru and @ping__) on this topic so they can provide more specific guidance!

What other authentication challenges are you facing?

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

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3732600352 --> @better-auth-agent[bot] commented on GitHub (Jan 10, 2026): It seems you're encountering issues with getting Better Auth to create HS256 signed JWTs instead of EdDSA signed JWTs. While Better Auth does support HS256, the current implementation might have limitations. There are discussions about the support for HS256 in relation to OIDC. You'll want to ensure that you are using the JWT plugin correctly in your configuration [[1]](https://github.com/better-auth/better-auth/pull/2912), and if you're following the correct protocol for generating your desired token type. However, based on the information, you might need to check for any specific flags or configurations that allow you to generate HS256 tokens instead of the default EdDSA signatures. If you haven’t already, I recommend trying the following: - Confirm that you have set up the JWT plugin correctly in your auth configuration and specified HS256 as the algorithm. - Keep an eye on the latest updates or issues in the Better Auth GitHub repository, as this could provide insights into similar situations faced by other developers. If you're still having issues, consider tagging Beka and Max (@bekacru and @ping__) on this topic so they can provide more specific guidance! What other authentication challenges are you facing? _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/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

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

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

Better Auth’s JWT plugin does not support HS256 (symmetric key) JWTs—it’s built for asymmetric algorithms like EdDSA, RS256, and ES256 only. That’s why trying to set alg: "HS256" in the JWT plugin config has no effect and always results in EdDSA-signed tokens. This is a known limitation and has been discussed as a feature request; maintainers suggest writing a custom plugin if you need full HS256 support in the JWT plugin context (source).

However, you can get HS256-signed JWTs for session data by enabling the session cookie cache strategy with strategy: "jwt". This will create a better-auth.session_data cookie containing a JWT signed with HS256 using your server secret. You do not need the JWT plugin or the JWKS table for this—just set the config as follows:

export const auth = betterAuth({
  emailAndPassword: { enabled: true },
  session: {
    cookieCache: {
      enabled: true,
      maxAge: 7 * 24 * 60 * 60, // 7 days
      strategy: "jwt", // enables HS256 JWTs for session_data
      refreshCache: true,
    },
  },
});

To verify this JWT in your Python backend, use your shared secret and any standard JWT library (like pyjwt). The JWT will be in the better-auth.session_data cookie.

You do not need the JWT plugin or JWKS for this setup—those are only for asymmetric JWTs (source). If you need HS256 for other types of tokens, you’d need to implement a custom plugin or sign those tokens yourself.

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:3732624867 --> @dosubot[bot] commented on GitHub (Jan 10, 2026): <!-- Greeting --> Hi @rjungbeck! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Better Auth’s JWT plugin does not support HS256 (symmetric key) JWTs—it’s built for asymmetric algorithms like EdDSA, RS256, and ES256 only. That’s why trying to set `alg: "HS256"` in the JWT plugin config has no effect and always results in EdDSA-signed tokens. This is a known limitation and has been discussed as a feature request; maintainers suggest writing a custom plugin if you need full HS256 support in the JWT plugin context ([source](https://github.com/better-auth/better-auth/issues/390)). However, you can get HS256-signed JWTs for session data by enabling the session cookie cache strategy with `strategy: "jwt"`. This will create a `better-auth.session_data` cookie containing a JWT signed with HS256 using your server secret. You do not need the JWT plugin or the JWKS table for this—just set the config as follows: ```typescript export const auth = betterAuth({ emailAndPassword: { enabled: true }, session: { cookieCache: { enabled: true, maxAge: 7 * 24 * 60 * 60, // 7 days strategy: "jwt", // enables HS256 JWTs for session_data refreshCache: true, }, }, }); ``` To verify this JWT in your Python backend, use your shared secret and any standard JWT library (like `pyjwt`). The JWT will be in the `better-auth.session_data` cookie. You do not need the JWT plugin or JWKS for this setup—those are only for asymmetric JWTs ([source](https://github.com/better-auth/better-auth/discussions/6153)). If you need HS256 for other types of tokens, you’d need to implement a custom plugin or sign those tokens yourself. <!-- 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/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/90b9f6ab-734e-4b30-a85c-a2169b4b0dd3?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=Better%20Auth%E2%80%99s%20JWT%20plugin%20does%20not%20support%20HS256%20%28symmetric%20key%29%20JWTs%E2%80%94it%E2%80%99s%20built%20for%20asymmetric%20algorithms%20like%20EdDSA%2C%20RS256%2C%20and%20ES256%20only.%20That%E2%80%99s%20why%20trying%20to%20set%20%60alg%3A%20%22HS256%22%60%20in%20the%20JWT%20plugin%20config%20has%20no%20effect%20and%20always%20results%20in%20EdDSA-signed%20tokens.%20This%20is%20a%20known%20limitation%20and%20has%20been%20discussed%20as%20a%20feature%20request%3B%20maintainers%20suggest%20writing%20a%20custom%20plugin%20if%20you%20need%20full%20HS256%20support%20in%20the%20JWT%20plugin%20context%C2%A0%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/390%29%29.%0A%0AHowever%2C%20you%20can%20get%20HS256-signed%20JWTs%20for%20session%20data%20by%20enabling%20the%20session%20cookie%20cache%20strategy%20with%20%60strategy%3A%20%22jwt%22%60.%20This%20will%20create%20a%20%60better-auth.session_data%60%20cookie%20containing%20a%20JWT%20signed%20with%20HS256%20using%20your%20server%20secret.%20You%20do%20not%20need%20the%20JWT%20plugin%20or%20the%20JWKS%20table%20for%20this%E2%80%94just%20set%20the%20config%20as%20follows%3A%0A%0A%60%60%60typescript%0Aexport%20const%20auth%20%3D%20betterAuth%28%7B%0A%20%20emailAndPassword%3A%20%7B%20enabled%3A%20true%20%7D%2C%0A%20%20session%3A%20%7B%0A%20%20%20%20cookieCache%3A%20%7B%0A%20%20%20%20%20%20enabled%3A%20true%2C%0A%20%20%20%20%20%20maxAge%3A%207%20%2A%2024%20%2A%2060%20%2A%2060%2C%20//%207%20days%0A%20%20%20%20%20%20strategy%3A%20%22jwt%22%2C%20//%20enables%20HS256%20JWTs%20for%20session_data%0A%20%20%20%20%20%20refreshCache%3A%20true%2C%0A%20%20%20%20%7D%2C%0A%20%20%7D%2C%0A%7D%29%3B%0A%60%60%60%0A%0ATo%20verify%20this%20JWT%20in%20your%20Python%20backend%2C%20use%20your%20shared%20secret%20and%20any%20standard%20JWT%20library%20%28like%20%60pyjwt%60%29.%20The%20JWT%20will%20be%20in%20the%20%60better-auth.session_data%60%20cookie.%0A%0AYou%20do%20not%20need%20the%20JWT%20plugin%20or%20JWKS%20for%20this%20setup%E2%80%94those%20are%20only%20for%20asymmetric%20JWTs%C2%A0%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/discussions/6153%29%29.%20If%20you%20need%20HS256%20for%20other%20types%20of%20tokens%2C%20you%E2%80%99d%20need%20to%20implement%20a%20custom%20plugin%20or%20sign%20those%20tokens%20yourself.)&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/7245)
Author
Owner

@rjungbeck commented on GitHub (Jan 11, 2026):

@dosu: I need to overwrite definePayload to include additional fields into the token. That is why I used the jwt plugin. I see only complexity (and more resource usage) when I need a public kery signatures for short lived session tokens, that I need to verify on different systems whith each web request. So I would have to cache the verified session tokens on the other systems.

<!-- gh-comment-id:3735368013 --> @rjungbeck commented on GitHub (Jan 11, 2026): @dosu: I need to overwrite definePayload to include additional fields into the token. That is why I used the jwt plugin. I see only complexity (and more resource usage) when I need a public kery signatures for short lived session tokens, that I need to verify on different systems whith each web request. So I would have to cache the verified session tokens on the other systems.
Author
Owner

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

There isn’t currently a way to customize the payload of HS256 session JWTs (created via session.cookieCache.strategy: "jwt") in Better Auth—there’s no definePayload or similar hook for these tokens. The session JWT just serializes the session/account data as-is, so any extra fields you want must be added to the session object itself (which also means they’ll be persisted in the session store, not just in the JWT) reference.

The definePayload option in the jwt plugin only works for asymmetric JWTs (EdDSA, RS256, ES256), not for the HS256 session JWTs reference. If you need more control over the HS256 session JWT payload, you’d have to fork or extend the session cookie logic.

If you just want to add transient fields, you could use session lifecycle hooks to inject them into the session object before it’s encoded, but this isn’t as flexible as definePayload and will affect the stored session data as well.

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:3735390897 --> @dosubot[bot] commented on GitHub (Jan 11, 2026): <!-- Answer --> There isn’t currently a way to customize the payload of HS256 session JWTs (created via session.cookieCache.strategy: "jwt") in Better Auth—there’s no definePayload or similar hook for these tokens. The session JWT just serializes the session/account data as-is, so any extra fields you want must be added to the session object itself (which also means they’ll be persisted in the session store, not just in the JWT) [reference](https://github.com/better-auth/better-auth/blob/f0a6f9448566ffa7f40f51bc881f72448f28836f/packages/better-auth/src/cookies/session-store.ts#L27-L307). The definePayload option in the jwt plugin only works for asymmetric JWTs (EdDSA, RS256, ES256), not for the HS256 session JWTs [reference](https://github.com/better-auth/better-auth/pull/2755). If you need more control over the HS256 session JWT payload, you’d have to fork or extend the session cookie logic. If you just want to add transient fields, you could use session lifecycle hooks to inject them into the session object before it’s encoded, but this isn’t as flexible as definePayload and will affect the stored session data as well. <!-- 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/71da5021-c458-4796-b6cc-83565837daf0?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/71da5021-c458-4796-b6cc-83565837daf0?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/71da5021-c458-4796-b6cc-83565837daf0?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/71da5021-c458-4796-b6cc-83565837daf0?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/71da5021-c458-4796-b6cc-83565837daf0?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/71da5021-c458-4796-b6cc-83565837daf0?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/71da5021-c458-4796-b6cc-83565837daf0?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=There%20isn%E2%80%99t%20currently%20a%20way%20to%20customize%20the%20payload%20of%20HS256%20session%20JWTs%20%28created%20via%20session.cookieCache.strategy%3A%20%22jwt%22%29%20in%20Better%20Auth%E2%80%94there%E2%80%99s%20no%20definePayload%20or%20similar%20hook%20for%20these%20tokens.%20The%20session%20JWT%20just%20serializes%20the%20session/account%20data%20as-is%2C%20so%20any%20extra%20fields%20you%20want%20must%20be%20added%20to%20the%20session%20object%20itself%20%28which%20also%20means%20they%E2%80%99ll%20be%20persisted%20in%20the%20session%20store%2C%20not%20just%20in%20the%20JWT%29%C2%A0%5Breference%5D%28https%3A//github.com/better-auth/better-auth/blob/f0a6f9448566ffa7f40f51bc881f72448f28836f/packages/better-auth/src/cookies/session-store.ts%23L27-L307%29.%0A%0AThe%20definePayload%20option%20in%20the%20jwt%20plugin%20only%20works%20for%20asymmetric%20JWTs%20%28EdDSA%2C%20RS256%2C%20ES256%29%2C%20not%20for%20the%20HS256%20session%20JWTs%C2%A0%5Breference%5D%28https%3A//github.com/better-auth/better-auth/pull/2755%29.%20If%20you%20need%20more%20control%20over%20the%20HS256%20session%20JWT%20payload%2C%20you%E2%80%99d%20have%20to%20fork%20or%20extend%20the%20session%20cookie%20logic.%0A%0AIf%20you%20just%20want%20to%20add%20transient%20fields%2C%20you%20could%20use%20session%20lifecycle%20hooks%20to%20inject%20them%20into%20the%20session%20object%20before%20it%E2%80%99s%20encoded%2C%20but%20this%20isn%E2%80%99t%20as%20flexible%20as%20definePayload%20and%20will%20affect%20the%20stored%20session%20data%20as%20well.)&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/7245)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10769