Skip to content

Bug: JWK passed as secret is not recognized as a public key #118

@FairyScript

Description

@FairyScript

What version of Elysia is running?

No response

What platform is your computer?

No response

What steps can reproduce the bug?

when using a JWK to sign and verify tokens, the presence of the d property in the JWK (used for signing) causes token verification to fail. During verification, it triggers the error “JSON Web Key for this operation must be a public JWK”, resulting in the verification always returning false.

sandbox url: https://codesandbox.io/p/devbox/hlxmfy?file=%2Fhttp.ts%3A27%2C41

a possible solution is to separate the d property when passing the JWK as the secret, and use a version of the JWK without d as the public key.
Below is my workaround.

diff --git a/src/index.ts b/src/index.ts
index 566a6a4..171cc00 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -203,9 +203,9 @@ export const jwt = <
 JWTOption<Name, Schema>) => {
 	if (!secret) throw new Error("Secret can't be empty")
 
-	const key =
+	const privateKey =
 		typeof secret === 'string' ? new TextEncoder().encode(secret) : secret
-
+	const publicKey = typeof privateKey === 'object' && 'd' in privateKey ? Object.assign({}, secret, { d: undefined }) : privateKey
 	const validator = schema
 		? getSchemaValidator(
 				t.Intersect([
@@ -359,7 +359,7 @@ JWTOption<Name, Schema>) => {
 				jwt = jwt.setIssuedAt(new Date())
 			}
 
-			return jwt.sign(key)
+			return jwt.sign(privateKey)
 		},
 		async verify(
 			jwt?: string,
@@ -374,8 +374,8 @@ JWTOption<Name, Schema>) => {
 			try {
 				const data: any = (
 					await (options
-						? jwtVerify(jwt, key, options)
-						: jwtVerify(jwt, key))
+						? jwtVerify(jwt, publicKey, options)
+						: jwtVerify(jwt, publicKey))
 				).payload
 
 				if (validator && !validator.Check(data))

a potential issue is that, according to RFC 7517 Appendix A.2, I can only confirm that the d parameter represents the private key value for RSA and EC algorithms. It is currently unclear whether this applies to all supported algorithms. We may need accompanying unit tests to ensure this functionality works as expected

What is the expected behavior?

No response

What do you see instead?

No response

Additional information

dependencies:

"@elysiajs/jwt": "^1.4.0",
"elysia": "^1.4.18",

Have you try removing the node_modules and bun.lockb and try again yet?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions