[GH-ISSUE #3226] Invalid keyPairConfig options available to user #9529

Closed
opened 2026-04-13 05:01:37 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @LightTab2 on GitHub (Jun 30, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3226

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Pass

 {
	alg: "EdDSA",
	crv: "Ed448",
}

or

 {
	alg: "ECDH-ES",
	crv: any of ["P-256" | "P-384" | "P-521"],
}

to

plugins: [
	jwt({
		jwks: {
			keyPairConfig: {
				...
			},
		}),
	],

Current vs. Expected behavior

Expected:

These options should not be allowed

Current:

 {
	alg: "EdDSA",
	crv: "Ed448",
}

uses "Ed25519" instead.

 {
	alg: "ECDH-ES",
	crv: any of ["P-256" | "P-384" | "P-521"],
}

cannot be used to sign tokens.

What version of Better Auth are you using?

1.2.12

Provide environment information

Irrelevant

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

Backend

Auth config (if applicable)


Additional context

According to JOSE Algorithm Key Requirements EdDSA algorithm needs to be used with Ed25519 curve.

These bugs were found while writing tests for PR #3219 solving another issue #3218 , related comment:

Tests concerning 'ECDH-ES' are also failing.

I inspected the private keys and they have no 'sing' usage assigned to them:

CryptoKey {
  type: 'private',
  extractable: false,
  algorithm: { name: 'ECDH', namedCurve: 'P-256' },
  usages: [ 'deriveBits' ]
}

example of another key:

CryptoKey {
  type: 'private',
  extractable: false,
  algorithm: {
    name: 'RSASSA-PKCS1-v1_5',
    modulusLength: 2048,
    publicExponent: [Uint8Array],
    hash: [Object]
  },
  usages: [ 'sign' ]
}

This one has that field.

It is apparently pre-Diffie-Hellman, we would need to use deriveBits to create a common secret and then an actual key for signing.
I will drop test support for this case (not sure if that's a valid move eww)

Originally posted by @LightTab2 in https://github.com/better-auth/better-auth/issues/3219#issuecomment-3017310172

Originally created by @LightTab2 on GitHub (Jun 30, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3226 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Pass ```js { alg: "EdDSA", crv: "Ed448", } ``` or ```js { alg: "ECDH-ES", crv: any of ["P-256" | "P-384" | "P-521"], } ``` to ```js plugins: [ jwt({ jwks: { keyPairConfig: { ... }, }), ], ``` ### Current vs. Expected behavior ### Expected: These options should not be allowed ### Current: ```js { alg: "EdDSA", crv: "Ed448", } ``` uses "**Ed25519**" instead. ```js { alg: "ECDH-ES", crv: any of ["P-256" | "P-384" | "P-521"], } ``` cannot be used to sign tokens. ### What version of Better Auth are you using? 1.2.12 ### Provide environment information ```bash Irrelevant ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript ``` ### Additional context According to JOSE [Algorithm Key Requirements](https://github.com/panva/jose/issues/210) **EdDSA** algorithm needs to be used with **Ed25519** curve. These bugs were found while writing tests for PR #3219 solving another issue #3218 , related comment: > Tests concerning 'ECDH-ES' are also failing. > > I inspected the **private keys** and they have no 'sing' usage assigned to them: ```js CryptoKey { type: 'private', extractable: false, algorithm: { name: 'ECDH', namedCurve: 'P-256' }, usages: [ 'deriveBits' ] } ``` > example of another key: ```js CryptoKey { type: 'private', extractable: false, algorithm: { name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: [Uint8Array], hash: [Object] }, usages: [ 'sign' ] } ``` > This one has that field. > > It is apparently pre-Diffie-Hellman, we would need to use deriveBits to create a common secret and then an actual key for signing. > I will drop test support for this case (not sure if that's a valid move eww) _Originally posted by @LightTab2 in https://github.com/better-auth/better-auth/issues/3219#issuecomment-3017310172_
GiteaMirror added the lockedbug labels 2026-04-13 05:01:37 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jun 30, 2025):

You're correct—Better Auth's jwt plugin currently allows passing keyPairConfig options like { alg: "EdDSA", crv: "Ed448" } or { alg: "ECDH-ES", crv: "P-256" }, but these are not properly validated. For EdDSA, only Ed25519 is supported for signing in JOSE; if you specify Ed448, the implementation silently falls back to Ed25519 instead of throwing an error. For ECDH-ES, it's a key agreement algorithm, not a signing algorithm, so keys generated this way can't be used to sign tokens—they only have deriveBits usage, not sign usage, which matches what you observed in your tests. There is no comprehensive validation in the codebase to prevent these mismatches, so invalid configs can slip through and either fail silently or just not work as expected (source).

The correct config for signing JWTs is { alg: "EdDSA", crv: "Ed25519" }, or you can use RSA/EC algorithms like RS256, ES256, or ES512 as documented. ECDH-ES should not be used for signing. If you want stricter validation, you’d need to add explicit checks for allowed algorithm/curve combinations in your own code or propose a validation enhancement upstream.

Your plan to drop test support for ECDH-ES signing is correct—it's not a valid use case. If you need references, see the jwt plugin code and the JOSE algorithm requirements.

To reply, just mention @dosu.


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

<!-- gh-comment-id:3019124349 --> @dosubot[bot] commented on GitHub (Jun 30, 2025): <!-- Answer --> You're correct—Better Auth's jwt plugin currently allows passing keyPairConfig options like `{ alg: "EdDSA", crv: "Ed448" }` or `{ alg: "ECDH-ES", crv: "P-256" }`, but these are not properly validated. For EdDSA, only Ed25519 is supported for signing in JOSE; if you specify Ed448, the implementation silently falls back to Ed25519 instead of throwing an error. For ECDH-ES, it's a key agreement algorithm, not a signing algorithm, so keys generated this way can't be used to sign tokens—they only have `deriveBits` usage, not `sign` usage, which matches what you observed in your tests. There is no comprehensive validation in the codebase to prevent these mismatches, so invalid configs can slip through and either fail silently or just not work as expected ([source](https://github.com/better-auth/better-auth/blob/7c4719ed77941bc1a685dc16550be10ad980f3df/packages/better-auth/src/plugins/jwt/index.ts)). The correct config for signing JWTs is `{ alg: "EdDSA", crv: "Ed25519" }`, or you can use RSA/EC algorithms like RS256, ES256, or ES512 as documented. ECDH-ES should not be used for signing. If you want stricter validation, you’d need to add explicit checks for allowed algorithm/curve combinations in your own code or propose a validation enhancement upstream. Your plan to drop test support for ECDH-ES signing is correct—it's not a valid use case. If you need references, see the [jwt plugin code](https://github.com/better-auth/better-auth/blob/7c4719ed77941bc1a685dc16550be10ad980f3df/packages/better-auth/src/plugins/jwt/index.ts) and the [JOSE algorithm requirements](https://github.com/panva/jose/issues/210). <!-- 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/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/4b663c4b-15c5-4363-9f8e-dea4e5cfefb2?feedback_type=other)</sup>&nbsp;&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/3226)
Author
Owner

@LightTab2 commented on GitHub (Sep 14, 2025):

It was fixed by #4161

<!-- gh-comment-id:3289056832 --> @LightTab2 commented on GitHub (Sep 14, 2025): It was fixed by #4161
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9529