Skip to content

feat(core,jose): add JWK support across core and jose packages#159

Merged
halvaradop merged 2 commits intomasterfrom
feat/add-jwk-support
Apr 28, 2026
Merged

feat(core,jose): add JWK support across core and jose packages#159
halvaradop merged 2 commits intomasterfrom
feat/add-jwk-support

Conversation

@halvaradop
Copy link
Copy Markdown
Member

@halvaradop halvaradop commented Apr 28, 2026

Summary by CodeRabbit

  • New Features

    • JOSE signing and encryption functions now accept JWK (JSON Web Key) asymmetric key pair formats for JWT operations, expanding supported key input types alongside existing formats.
  • Tests

    • Added comprehensive test coverage for JWK-based signing, encryption, and combined JWT workflows.

@halvaradop halvaradop added enhancement New feature or request feature New functionality experimental labels Apr 28, 2026
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
auth Skipped Skipped Apr 28, 2026 8:10pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Warning

Rate limit exceeded

@halvaradop has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 17 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a439a207-e08f-4bda-b930-eb231a58bb1c

📥 Commits

Reviewing files that changed from the base of the PR and between fa333e2 and 4a1e6d5.

📒 Files selected for processing (7)
  • packages/core/CHANGELOG.md
  • packages/core/src/@types/session.ts
  • packages/core/src/shared/assert.ts
  • packages/jose/CHANGELOG.md
  • packages/jose/src/assert.ts
  • packages/jose/src/deriveKey.ts
  • packages/jose/src/secret.ts
📝 Walkthrough

Walkthrough

This PR extends JWT and JOSE operations to accept JWK-formatted cryptographic keys alongside existing CryptoKey and CryptoKeyPair representations. It introduces new AsymmetricKeyPair type definitions, runtime type guards, a key export utility, and updates secret dispatch logic across signing, encryption, and derivation modules to handle JWK inputs correctly.

Changes

Cohort / File(s) Summary
Type definitions
packages/core/src/@types/session.ts, packages/jose/src/index.ts
Added AsymmetricKeyPair interface with publicKey/privateKey supporting both CryptoKey and JWK. Extended SecretKey and JWTSecretInput union types to include JWK and AsymmetricKeyPair.
Type guards and validators
packages/core/src/shared/assert.ts, packages/jose/src/assert.ts
Added runtime type guards: isKeyPair(), isJWKFormattedKey() in core; renamed isCryptoKeyPair to isAsymmetricKeyPair() and added isJWKKey() in JOSE package. All validate asymmetric key pair and JWK structures.
Crypto utilities
packages/core/src/shared/crypto.ts
Introduced exportJWKKeyPair() function to generate algorithm-specific key pairs and export both public/private keys to JWK format.
Secret dispatch and derivation
packages/core/src/jose.ts, packages/jose/src/secret.ts, packages/jose/src/deriveKey.ts
Updated getSecrets(), createSecret(), getJWSSecrets(), and getJWESecrets() to recognize and handle asymmetric key pair inputs. Added JWK rejection in createDeriveKey() to prevent HKDF derivation from JWK-form inputs.
Signing and encryption factories
packages/jose/src/sign.ts, packages/jose/src/encrypt.ts
Updated createJWS and createJWE/createCompactJWE function signatures to accept JWTSecretInput and switched key-shape detection from isCryptoKeyPair to isAsymmetricKeyPair.
Test coverage
packages/core/test/jose.test.ts, packages/jose/test/index.test.ts
Added comprehensive integration tests for JWK-based key material across JWS (RS256), JWE (RSA-OAEP-256 with A256GCM), and combined JWT flows with separate signing/encryption key pairs.
Documentation
packages/jose/CHANGELOG.md
Updated changelog to document new asymmetric cryptography support via JWK key pairs alongside existing CryptoKeyPair support.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Hops skip through key forests of JWK delight,
AsymmetricKeyPairs shining cryptographic bright!
Guards and type checks stand tall with care,
From CryptoKey to JSON Web Keys, magic everywhere!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main objective: adding JWK (JSON Web Key) support to both the core and jose packages, which is reflected throughout all changeset modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-jwk-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
packages/jose/CHANGELOG.md (1)

13-14: Clarify the distinction from the CryptoKeyPair entry.

The new JWK entry (line 13) and the existing CryptoKeyPair entry (line 15) list identical functions and use very similar wording, which may confuse readers about what differentiates them. The key distinction is that this PR extends the existing asymmetric cryptography support to also accept JWK-formatted keys as input, not that it adds asymmetric cryptography capabilities for the first time.

Consider rewording to make this clearer:

📝 Suggested rewording
-Added support to asymmetric cryptography using JWK key pairs across JOSE functions, including the dedicated `signJWS`, `verifyJWS`, `encryptJWE`, `decryptJWE`, `encryptCompactJWE`, `decryptCompactJWE`, `encodeJWT`, and `decodeJWT` functions, as well as the factory functions `createJWS`, `createJWE`, and `createJWT`. [`#159`](https://github.com/aura-stack-ts/auth/pull/159)
+Extended asymmetric cryptography support to accept JWK (JSON Web Key) format keys in addition to `CryptoKeyPair` across JOSE functions, including the dedicated `signJWS`, `verifyJWS`, `encryptJWE`, `decryptJWE`, `encryptCompactJWE`, `decryptCompactJWE`, `encodeJWT`, and `decodeJWT` functions, as well as the factory functions `createJWS`, `createJWE`, and `createJWT`. [`#159`](https://github.com/aura-stack-ts/auth/pull/159)

Alternatively, consider combining both entries into a single entry that mentions both CryptoKeyPair and JWK format support were added together, if that better reflects the user-facing capability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/jose/CHANGELOG.md` around lines 13 - 14, Update the CHANGELOG entry
to clearly distinguish JWK input support from the existing CryptoKeyPair
support: reword the JWK line so it states that the listed functions (signJWS,
verifyJWS, encryptJWE, decryptJWE, encryptCompactJWE, decryptCompactJWE,
encodeJWT, decodeJWT and the factories createJWS, createJWE, createJWT) now also
accept JWK-formatted keys as input, rather than implying asymmetric cryptography
was newly added; alternatively merge the two entries into one that explicitly
notes both CryptoKeyPair and JWK format support were added for those functions.
packages/core/src/shared/assert.ts (1)

130-132: isKeyPair duplicates isCryptoKeyPair behavior.

Both guards currently use the same predicate (publicKey + privateKey presence), which makes intent and call sites harder to reason about. Consider consolidating into one guard (or making one a thin alias) to keep dispatch logic simpler.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/shared/assert.ts` around lines 130 - 132, The two type
guards isKeyPair and isCryptoKeyPair duplicate the same predicate (checking for
publicKey and privateKey), so consolidate them: keep a single implementation
(choose one name, e.g., isCryptoKeyPair) that performs the object/null +
"publicKey" in value + "privateKey" in value check, and make the other function
a thin alias that returns that call (or remove it and update call sites to the
retained name); update exports so only one implementation contains the logic and
the other simply delegates to it to preserve compatibility.
packages/jose/src/assert.ts (1)

28-30: Consider validating key-pair member shapes, not only field presence.

This guard currently accepts any { publicKey, privateKey } object. A lightweight nested validation (CryptoKey or JWK-shaped object) would reduce deferred runtime errors in downstream JOSE operations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/jose/src/assert.ts` around lines 28 - 30, The type guard
isAsymmetricKeyPair currently only checks for the presence of
publicKey/privateKey fields; update it to perform lightweight shape validation
of those members (e.g., verify each is a CryptoKey-like object or a minimal
JWK-like shape) to avoid accepting arbitrary objects. Implement or reuse a
helper (e.g., isCryptoKey or isJwkShape) that checks member properties such as
typeof === "object" && member !== null and either instanceOf CryptoKey (if
available) or presence of minimal JWK fields like "kty" and "crv"/"alg" as
appropriate, then call that helper for both publicKey and privateKey inside
isAsymmetricKeyPair so the guard returns true only when both members match the
expected key shape. Ensure helpers and type predicate signatures align with
AsymmetricKeyPair so downstream code gets proper narrowed types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/`@types/session.ts:
- Line 6: Change the JWK import to a type-only import since JWK is used only in
type positions: replace the current import of JWK (symbol JWK) with an "import
type" form to match other type imports in this file (session-related types
referenced on lines where JWK appears such as interfaces using JWK). Ensure no
runtime import is introduced so the module only imports JWK for type-checking.

In `@packages/core/src/shared/assert.ts`:
- Line 11: The import for JWK should be a type-only import to avoid runtime
export inconsistencies: change the runtime import "import { JWK } from
'@aura-stack/jose/jose'" to a type import ("import type { JWK } ...") so JWK is
treated purely as a TypeScript type used in the type predicate (the JWK
reference around line 173) and no runtime module export is required; update the
import declaration where JWK is brought in and leave all usages (including the
type predicate) unchanged.

In `@packages/jose/src/assert.ts`:
- Around line 32-34: The isJWKKey type guard currently treats any object with a
kty property as a JWK; update the isJWKKey function to first ensure value is a
non-null object and then verify that value.kty exists and is a string (e.g.,
check typeof (value as any).kty === "string") so malformed non-string kty values
don't pass; adjust the return predicate in isJWKKey accordingly (reference
function name isJWKKey and the JsonWebKey type).

In `@packages/jose/src/deriveKey.ts`:
- Around line 67-68: The thrown KeyDerivationError message in deriveKey.ts is
stale: the branch checks "secretKey instanceof CryptoKey || isJWKKey(secretKey)"
but the message only mentions CryptoKey; update the KeyDerivationError thrown by
this conditional (referencing secretKey, isJWKKey, and KeyDerivationError in
deriveKey.ts) to mention both CryptoKey and JWK inputs (e.g., "Cannot derive key
from CryptoKey or JWK. Use Uint8Array or string secret instead.") so the error
accurately reflects the rejected types.

In `@packages/jose/src/secret.ts`:
- Line 54: The InvalidSecretError message thrown in createSecret is outdated: it
mentions AsymmetricKeyPair while createSecret now accepts JWKs detected via
isJWKKey(secret). Update the error text in the throw (InvalidSecretError) to
list the actual accepted types (e.g., "Secret must be a string, Uint8Array,
CryptoKey or JWK") or otherwise include JWK so the message matches the
createSecret and isJWKKey(secret) logic.

---

Nitpick comments:
In `@packages/core/src/shared/assert.ts`:
- Around line 130-132: The two type guards isKeyPair and isCryptoKeyPair
duplicate the same predicate (checking for publicKey and privateKey), so
consolidate them: keep a single implementation (choose one name, e.g.,
isCryptoKeyPair) that performs the object/null + "publicKey" in value +
"privateKey" in value check, and make the other function a thin alias that
returns that call (or remove it and update call sites to the retained name);
update exports so only one implementation contains the logic and the other
simply delegates to it to preserve compatibility.

In `@packages/jose/CHANGELOG.md`:
- Around line 13-14: Update the CHANGELOG entry to clearly distinguish JWK input
support from the existing CryptoKeyPair support: reword the JWK line so it
states that the listed functions (signJWS, verifyJWS, encryptJWE, decryptJWE,
encryptCompactJWE, decryptCompactJWE, encodeJWT, decodeJWT and the factories
createJWS, createJWE, createJWT) now also accept JWK-formatted keys as input,
rather than implying asymmetric cryptography was newly added; alternatively
merge the two entries into one that explicitly notes both CryptoKeyPair and JWK
format support were added for those functions.

In `@packages/jose/src/assert.ts`:
- Around line 28-30: The type guard isAsymmetricKeyPair currently only checks
for the presence of publicKey/privateKey fields; update it to perform
lightweight shape validation of those members (e.g., verify each is a
CryptoKey-like object or a minimal JWK-like shape) to avoid accepting arbitrary
objects. Implement or reuse a helper (e.g., isCryptoKey or isJwkShape) that
checks member properties such as typeof === "object" && member !== null and
either instanceOf CryptoKey (if available) or presence of minimal JWK fields
like "kty" and "crv"/"alg" as appropriate, then call that helper for both
publicKey and privateKey inside isAsymmetricKeyPair so the guard returns true
only when both members match the expected key shape. Ensure helpers and type
predicate signatures align with AsymmetricKeyPair so downstream code gets proper
narrowed types.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2aff55ee-3b62-411e-8cc6-96c926629b42

📥 Commits

Reviewing files that changed from the base of the PR and between 9aeeeed and fa333e2.

📒 Files selected for processing (13)
  • packages/core/src/@types/session.ts
  • packages/core/src/jose.ts
  • packages/core/src/shared/assert.ts
  • packages/core/src/shared/crypto.ts
  • packages/core/test/jose.test.ts
  • packages/jose/CHANGELOG.md
  • packages/jose/src/assert.ts
  • packages/jose/src/deriveKey.ts
  • packages/jose/src/encrypt.ts
  • packages/jose/src/index.ts
  • packages/jose/src/secret.ts
  • packages/jose/src/sign.ts
  • packages/jose/test/index.test.ts

Comment thread packages/core/src/@types/session.ts Outdated
Comment thread packages/core/src/shared/assert.ts Outdated
Comment thread packages/jose/src/assert.ts
Comment thread packages/jose/src/deriveKey.ts Outdated
Comment thread packages/jose/src/secret.ts Outdated
@halvaradop halvaradop merged commit 66e51a6 into master Apr 28, 2026
7 checks passed
@halvaradop halvaradop deleted the feat/add-jwk-support branch April 28, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request experimental feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant