Skip to content

feat(jar): JWT-Secured Authorization Requests (JAR) support - #863

Merged
jd3vi1 merged 5 commits into
masterfrom
feature/jar
Aug 6, 2026
Merged

jd3vi1 merged 5 commits into
masterfrom
feature/jar

Conversation

@jd3vi1

@jd3vi1 jd3vi1 commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds support for JWT-Secured Authorization Requests (JAR, RFC 9101). When requestObjectSigningKey is configured, the SDK signs all authorization parameters into a JWT and sends it as the request parameter, so the /authorize redirect carries only client_id and request.

What's included

  • requestObjectSigningKey — private key used to sign the request object. Accepts the same formats as clientAssertionSigningKey (PEM string, Buffer, KeyObject, JWK, CryptoKey).
  • requestObjectSigningAlg — required whenever requestObjectSigningKey is set. Web Crypto algorithm names are not valid JWA alg values, so an explicit JWA algorithm is required (a shared ASYMMETRIC_SIGNING_ALGS list is used, matching clientAssertionSigningAlg).
  • requestObjectSigningKeyId — optional kid header on the request object JWT.
  • Works transparently on top of the existing PAR support. When PAR is enabled, the signed request object is POSTed to /oauth/par, which is the recommended FAPI pattern.
  • The request object's aud is set to the issuer identifier advertised in the discovery document (which may differ from issuerBaseURL, e.g. a trailing slash), as JAR requires.

Usage

app.use(
  auth({
    authorizationParams: { response_type: 'code' },
    requestObjectSigningKey: fs.readFileSync('./request-object-key.pem'),
    requestObjectSigningAlg: 'RS256',
    pushedAuthorizationRequests: true, // recommended
  }),
);

Tests

  • Unit tests for buildRequestObject (header, kid, standard claims, aud), config validation (alg required with key), and the login redirect (request param present, PAR combination).
  • An end-to-end test covering the combined PAR + JAR flow.
  • Type tests in index.test-d.ts.
  • Documentation in EXAMPLES.md and a runnable example at examples/jar.js.

Comment thread examples/jar.js Dismissed
@jd3vi1

jd3vi1 commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Addressed the nits in 7ff0457:

  1. aud fallback removed. buildRequestObject now requires the discovered issuer as its audience argument and throws if it is missing, so the issuerBaseURL fallback (the mismatch that triggers invalid_request_object) is gone. The unit tests now pass the discovered issuer explicitly and assert aud equals it.
  2. Non-PAR redirect coverage added. New test asserts the non-PAR authorize redirect carries only client_id and request.
  3. Empty-string key. requestObjectSigningKey now rejects '' at config validation, so the "is set" check is consistent between the schema and the login-side guard (previously '' forced alg required but silently skipped JAR).

Full suite and tsd green.

Comment thread examples/run_example.js Outdated
jd3vi1 added 3 commits August 3, 2026 18:16
Sign authorization request parameters into a JWT and send them as the
`request` parameter (RFC 9101). Enabled by setting `requestObjectSigningKey`
with a required `requestObjectSigningAlg`. Works alongside PAR, and the
request object's `aud` is set to the discovered issuer identifier.
…ing key

Address review feedback on JAR:
- buildRequestObject now requires the discovered issuer as its audience instead
  of falling back to issuerBaseURL, which produced the invalid_request_object
  mismatch the spec warns against. Tests pass the discovered issuer explicitly.
- Reject an empty-string requestObjectSigningKey at config validation so the
  'is set' check is consistent (Joi treated '' as set while the login-side check
  skipped JAR, silently disabling it).
- Add tests: buildRequestObject throws without audience, and the non-PAR
  authorize redirect carries only client_id and request.
…s example

The example dispatcher referenced 'hri.js', which does not exist in the
codebase (only examples/jar.js ships in this PR). Rename the leftover
'hri-client' registered client to 'jar-client' across the example
dispatcher, the e2e fixture, the JAR e2e test, and the example comment so
the example, its comment, and the fixture client agree.
Comment thread index.d.ts Outdated
Comment thread EXAMPLES.md

The request object's `aud` is set to the issuer identifier advertised in the discovery document (which may differ from `issuerBaseURL`, e.g. a trailing slash), as JAR requires. `requestObjectSigningKey` accepts the same key formats as `clientAssertionSigningKey` (PEM string, Buffer, KeyObject, JWK, CryptoKey).

Full example at [jar.js](./examples/jar.js), to run it: `npm run start:example -- jar`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey @jd3vi1 based on the example added for this change, the accepted command to run the example app would be

npm run start:example -- jar.js
or 
npm run start:example -- jar

Can you please check ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i've made it agnostic of the extension, both should work now.

Comment thread EXAMPLES.md

## 16. JWT-Secured Authorization Requests (JAR)

[JAR](https://www.rfc-editor.org/rfc/rfc9101.html) (part of Auth0's Highly Regulated Identity feature set) signs all authorization parameters into a JWT and sends them as the `request` parameter, so the `/authorize` redirect carries only `client_id` and `request`. Set `requestObjectSigningKey` to enable it. `requestObjectSigningAlg` is always required, since Web Crypto algorithm names are not valid JWA `alg` values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@jd3vi1 we should showcase or provide some reference how users can get/generate requestObjectSigningKey and also reference for allowed requestObjectSigningAlg

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added

run_example.js now strips a trailing `.js` from the example argument so
`npm run start:example -- jar` (as documented) selects the JAR-capable
`jar-client`, matching the `-- jar.js` form.

EXAMPLES.md now lists the accepted `requestObjectSigningAlg` values and
shows how to generate an RSA or EC signing key pair for JAR.
@jd3vi1
jd3vi1 requested a review from gyaneshgouraw August 5, 2026 14:21
@jd3vi1
jd3vi1 merged commit 950c5b0 into master Aug 6, 2026
11 checks passed
@jd3vi1
jd3vi1 deleted the feature/jar branch August 6, 2026 06:33
@jd3vi1 jd3vi1 mentioned this pull request Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants