Skip to content

Add DPoP support to keycloak-js#253

Open
sundayScoop wants to merge 1 commit intokeycloak:mainfrom
tide-foundation:dpop-support
Open

Add DPoP support to keycloak-js#253
sundayScoop wants to merge 1 commit intokeycloak:mainfrom
tide-foundation:dpop-support

Conversation

@sundayScoop
Copy link
Copy Markdown

@sundayScoop sundayScoop commented Jan 30, 2026

Add Demonstration of Proof-of-Possession (DPoP) token support as per the RFC, addressing issue #8.

Key Changes

  • Generate and manage public/private key pairs for each client session using IndexedDB unextractable keys
  • Create DPoP proof tokens if required by authorization server (on access/refresh token requests) or resource server
  • Added the secureFetch() wrapper so developers don't have to deal with DPoP flow management (e.g. new nonce provided)
  • Added comprehensive tests covering DPoP functionality

Testing

  • Added tests for DPoP token flows in dpop.spec.ts
  • All existing tests continue to pass

Notes

  • Section 10 was not implemented. This is due to it being OPTIONAL as stated in the RFC and its minimal security benefits.
  • RSA Algorithms were not added as supported key algorithms. Only Elliptical and Edwards curve algorithms were added.

Enabling DPoP Example

await keycloak.init({
    flow: 'implicit',
    useDPoP: { mode: 'auto' }
})

Closes #8

@sundayScoop sundayScoop force-pushed the dpop-support branch 3 times, most recently from 5cc24c1 to eb42d36 Compare February 5, 2026 05:16
@keycloak keycloak deleted a comment from williamjaackson Feb 17, 2026
@mposolda mposolda self-assigned this Feb 18, 2026
@mposolda mposolda requested a review from jonkoops February 18, 2026 15:45
@mposolda
Copy link
Copy Markdown
Contributor

@jonkoops Do you please have opportunity to review? I will try to review as well, but feedback from you would be welcome if you have a chance!

@jonkoops
Copy link
Copy Markdown
Contributor

Yes, I will take a look and review. Currently looking at the last bugs for 26.2 that I want to resolve, after that I am going to start merging in features and deprecations for 26.3.

Copy link
Copy Markdown
Contributor

@edewit edewit left a comment

Choose a reason for hiding this comment

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

👍

@edewit
Copy link
Copy Markdown
Contributor

edewit commented Feb 27, 2026

@sundayScoop can you fix the lint errors though

@sundayScoop
Copy link
Copy Markdown
Author

@edewit just fixed the lint errors, let me know if there's anything else needed

@edewit
Copy link
Copy Markdown
Contributor

edewit commented Mar 2, 2026

👍

@mposolda mposolda requested a review from graziang March 3, 2026 10:49
graziang
graziang previously approved these changes Mar 4, 2026
Copy link
Copy Markdown
Contributor

@graziang graziang left a comment

Choose a reason for hiding this comment

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

@sundayScoop Thanks, from a DPoP RFC point of view, it’s ok for me. I’ll leave to the others a more js-focused review.

@mposolda
Copy link
Copy Markdown
Contributor

mposolda commented Mar 6, 2026

@jonkoops Can you please reply here if you have a chance to review in the near future? Otherwise going to merge this without your review.

@graziang Thanks for your review!

@sundayScoop Thanks again for the PR! We may need also documentation for this feature in the keycloak.js documentation . See this directory https://github.com/keycloak/keycloak-js/tree/main/docs . Probably worth to introduce dedicated section about DPoP and document it here? Besides configuration options, it will be good to document:

  • Fact that crypto API needs to be available. It may be good to document also when it is typically available. I am thinking like a warning with something like DPoP requires Web Crypto API to be available in your browser. The availability of this API may be specific to the particular browser and browser version. The API is typically available just when https is used - I am not sure here, but you probably know more what typical limitations is....
  • It seems the PR supports just ES* and EdDSA algorithms. Is it correct? If yes, it will be also good to document

@jonkoops
Copy link
Copy Markdown
Contributor

jonkoops commented Mar 9, 2026

Please hold off on merging this PR until we have done a final patch release. I intend to merge this in for 26.3.0, together with some other work for a feature release.

@sundayScoop
Copy link
Copy Markdown
Author

sundayScoop commented Mar 10, 2026

@jonkoops Can you please reply here if you have a chance to review in the near future? Otherwise going to merge this without your review.

@graziang Thanks for your review!

@sundayScoop Thanks again for the PR! We may need also documentation for this feature in the keycloak.js documentation . See this directory https://github.com/keycloak/keycloak-js/tree/main/docs . Probably worth to introduce dedicated section about DPoP and document it here? Besides configuration options, it will be good to document:

  • Fact that crypto API needs to be available. It may be good to document also when it is typically available. I am thinking like a warning with something like DPoP requires Web Crypto API to be available in your browser. The availability of this API may be specific to the particular browser and browser version. The API is typically available just when https is used - I am not sure here, but you probably know more what typical limitations is....
  • It seems the PR supports just ES* and EdDSA algorithms. Is it correct? If yes, it will be also good to document

@mposolda regarding the crypto API suggestion - there is this check in keycloak-dpop.js:

if (typeof crypto === 'undefined' || !crypto.subtle) {
  throw new Error('DPoP requires Web Crypto API (crypto.subtle) which is not available in this environment.')
}

Were you thinking of explicitly showing a warning message to the user without an error? Or just improving the message in the error being thrown? I realise there's no mention of the https requirement in the error, so that might be good to add.

Aside from that I've just finished the requested docs - so nearly there!

@jonkoops
Copy link
Copy Markdown
Contributor

We already have places where we detect the Crypto API and throw if it is not found:

keycloak-js/lib/keycloak.js

Lines 1623 to 1625 in fa52139

if (typeof crypto === 'undefined' || typeof crypto.randomUUID === 'undefined') {
throw new Error('Web Crypto API is not available.')
}

keycloak-js/lib/keycloak.js

Lines 1689 to 1691 in fa52139

if (typeof crypto === 'undefined' || typeof crypto.getRandomValues === 'undefined') {
throw new Error('Web Crypto API is not available.')
}

keycloak-js/lib/keycloak.js

Lines 1946 to 1948 in fa52139

if (typeof crypto === 'undefined' || typeof crypto.subtle === 'undefined') {
throw new Error('Web Crypto API is not available.')
}

Keycloak JS relies on the Web Crypto API, and therefore only works in a secure context. Perhaps we can roll up this feature detection into a single utility function that is called in all the places where the API is called, to reduce repetition.

@mposolda
Copy link
Copy Markdown
Contributor

@jonkoops Can you please reply here if you have a chance to review in the near future? Otherwise going to merge this without your review.
@graziang Thanks for your review!
@sundayScoop Thanks again for the PR! We may need also documentation for this feature in the keycloak.js documentation . See this directory https://github.com/keycloak/keycloak-js/tree/main/docs . Probably worth to introduce dedicated section about DPoP and document it here? Besides configuration options, it will be good to document:

  • Fact that crypto API needs to be available. It may be good to document also when it is typically available. I am thinking like a warning with something like DPoP requires Web Crypto API to be available in your browser. The availability of this API may be specific to the particular browser and browser version. The API is typically available just when https is used - I am not sure here, but you probably know more what typical limitations is....
  • It seems the PR supports just ES* and EdDSA algorithms. Is it correct? If yes, it will be also good to document

@mposolda regarding the crypto API suggestion - there is this check in keycloak-dpop.js:

if (typeof crypto === 'undefined' || !crypto.subtle) {
  throw new Error('DPoP requires Web Crypto API (crypto.subtle) which is not available in this environment.')
}

Were you thinking of explicitly showing a warning message to the user without an error? Or just improving the message in the error being thrown? I realise there's no mention of the https requirement in the error, so that might be good to add.

Aside from that I've just finished the requested docs - so nearly there!

@sundayScoop I was concerned just about documentation here. It can be good to explicitly mention in the keycloak.js documentation that DPoP would be available just if Crypto API is available. And use some warning/formulation in the docs about this similar to what I've mentioned.

For example see some warning in the current keycloak.js documentation https://www.keycloak.org/securing-apps/javascript-adapter#_using_the_adapter (The warning in this section about "Silent check-sso functionality is limited in some modern browsers." )

@mposolda
Copy link
Copy Markdown
Contributor

Please hold off on merging this PR until we have done a final patch release. I intend to merge this in for 26.3.0, together with some other work for a feature release.

@jonkoops Cool, Thanks! Any ETA when it could be merged approximately? And when you plan 26.3.0 release?

@jonkoops
Copy link
Copy Markdown
Contributor

@jonkoops Cool, Thanks! Any ETA when it could be merged approximately? And when you plan 26.3.0 release?

At most in a couple of weeks. I am currently rather busy with my talk for BackstageCon, so my bandwidth is limited.

@sundayScoop
Copy link
Copy Markdown
Author

@mposolda just added the requested docs. Sorry for the delay - had quite a busy few weeks.

Let me know what you think of the docs

@mposolda
Copy link
Copy Markdown
Contributor

@jonkoops Cool, Thanks! Any ETA when it could be merged approximately? And when you plan 26.3.0 release?

At most in a couple of weeks. I am currently rather busy with my talk for BackstageCon, so my bandwidth is limited.

@jonkoops Thanks for the update

mposolda
mposolda previously approved these changes Mar 23, 2026
Copy link
Copy Markdown
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

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

@sundayScoop Thanks for the documentation! I am approving this PR from my point of view. The merge might be delayed though (See comments above from @jonkoops ), but hopefully we would be able to do it in few weeks

Update: There is the issue in Build guides . Are you able to take a look?

@mposolda mposolda self-requested a review March 23, 2026 08:59
@sundayScoop
Copy link
Copy Markdown
Author

Looking now

@sundayScoop
Copy link
Copy Markdown
Author

@mposolda npm run guides passed locally for me

@sundayScoop
Copy link
Copy Markdown
Author

@mposolda following some internal testing at my company, we've identified an issue with the current DPoP implementation related to browsers with unsynchronised clocks.

In my initial PR comment I noted:

iat is still generated on the browser — it would be good to source this from the authorization server instead

I'd say this is a necessity rather than a nice-to-have. A browser with a skewed clock will produce a DPoP proof that Keycloak rejects, as we observed with the following server-side error:

2026-03-25 10:01:44,055 WARN [org.keycloak.events] (executor-thread-188)
type="CODE_TO_TOKEN_ERROR", realmId="x", realmName="x", clientId="x",
userId="null", ipAddress="x", error="invalid_dpop_proof",
reason="DPoP proof is not active", grant_type="authorization_code",
client_auth_method="client-secret"

I'd recommend holding off on merging this PR until the iat value is adjusted using a timeSkew offset

@sundayScoop
Copy link
Copy Markdown
Author

Alright I added the timeSkew to the iat value that's part of the DPoP proof. Basically means any browser that has an out of sync time will work with DPoP enabled.

@sundayScoop
Copy link
Copy Markdown
Author

@mposolda is anything else needed?

@jonkoops
Copy link
Copy Markdown
Contributor

@sundayScoop I took a quick look at the PR, and find the implementation generally agreeable. I have a larger review queued up, but I would like to move this work to v27, as there are several deprecations that I need to do for v26 and a lot of code will be removed under v27. I'll keep you posted as I go.

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.

DPoP support in keycloak.js

5 participants