Skip to content
Connect2id
Connect2id server

Connect2id server 19.4

This Connect2id server release ships full DPoP support for applications using the token exchange grant. It also enables grant handler plugins to find out whether the issued access token is going to be mTLS or DPoP-bound, to inform authorisation decisions. Two old issues in the integration APIs receive a fix.

Exchange of DPoP access tokens

In January 2020 the OAuth working group published the final spec of the token exchange grant RFC 8693, for applications that need to exchange tokens, of any purpose and kind, for an access token, potentially accompanied by a refresh token and an ID token.

A common use case has been the exchange of one access token for another. For instance, to enable web APIs to obtain secondary, or downstream, access tokens for backend services. For access tokens of the bearer and the mTLS-bound type the token exchange is fully specified. However, for DPoP tokens, a crucial bit is not found in the spec - how to pass the required DPoP proof when the subject_token or the actor_token is DPoP. This gray area is due to the token exchange RFC 8693 predating DPoP RFC 9949 by a few years.

Connect2id made steps to address this situation in the OAuth WG on several occasions, and earlier this month an informal agreement was reached: to use the DPoP HTTP request header for the submitted as well as the newly issued access tokens. In order for this to work, the ath (access token hash) JWT claim, normally reserved for DPoP proofs for resource server access, is to be included in the DPoP proof that the client mints for the token endpoint.

Example token exchange request with a DPoP subject_token:

POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2I
 joiUC0yNTYiLCJ4IjoiNER4cHlGTTcxTVVTSzUyVnlGZVNMYUJoWTIzOUxSTkM5MTFPb1JGX3pEOCI
 sInkiOiI3MTBSOHpZUjlxakY2UHFGamVfaVN5eFBjdkNmdlFkNmM0QlNIclRidW5zIn19.eyJodG0i
 OiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9jMmlkLmNvbS90b2tlbiIsImF0aCI6InlhajNHRzJUZ1hlRG
 tGLTE0MW9iNlA1SkNNTmdKV3ZqLUliWFp0eEZ5RzQiLCJpYXQiOjE3NjE3MzAwMTksImp0aSI6ImM4
 VGVtUG5Qc1FLVmU1azBpR25WUkF5NmdzQ1FsN3V2THdnbGRMQ1NaUjgifQ.MBEDQTTgPQC5Dgo_CTl
 bceQRv9-YBE7RF59vGzIfOGhuQtHNt5ImxDgkHlG74eQYNHTIXNSvtfZ46DVHrMVkiw

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
 &client_id=123
 &subject_token=l_Lre_1cHe29DBDymbMxIQ.Wuy0HNMwgxgBaRZQcRCGIg
 &subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token
 &scope=

Note how the DPoP proof JWT includes a hash (ath) of the submitted access token, as if a protected resource is being accessed. The Connect2id server will use the ath to verify the binding of the proof to the subject_token:

{
  "htm" : "POST",
  "htu" : "https://c2id.com/token",
  "ath" : "yaj3GG2TgXeDkF-141ob6P5JCMNgJWvj-IbXZtxFyG4",
  "iat" : 1761730019,
  "jti" : "c8TemPnPsQKVe5k0iGnVRAy6gsCQl7uvLwgldLCSZR8"
}

The public JWK in DPoP proof JWT header will be used to check the client key binding to the subject_token and then to bind the newly issued DPoP access token:

{
  "typ" : "dpop+jwt",
  "alg" : "ES256",
  "jwk" : { "kty" : "EC", 
            "crv" : "P-256",
            "x"   : "4DxpyFM71MUSK52VyFeSLaBhY239LRNC911OoRF_zD8",
            "y"   : "710R8zYR9qjF6PqFje_iSyxPcvCfvQd6c4BSHrTbuns"
  }
}

The use of DPoP access tokens and proofs is explained in the docs for token exchange grant handler and the token endpoint.

Finding out the token binding method in a grant handler plugin

The available grant handler SPIs were updated to enable plugins to find out whether the issued access token is going to be sender-constrained via mTLS or DPoP:

This can be used to inform authorisation decisions, for example what lifetime to assign to the issued refresh token.

A plugin can obtain the applicable binding by calling the GrantHandlerContext.getTokenBindingMethods which returns a Set<TokenBindingMethod>:

  • If the set is empty the access token is simple bearer access token.
  • Otherwise the set contains an enum of
    • TokenBindingMethod.MTLS
    • TokenBindingMethod.DPOP

When an access token is sender-constrained, this is normally done by a single binding method.

Fixed issues

This release fixes two issues in the authorisation session API and the direct authorisation API. In cases when the client is not registered in the grant_types metadata to use refresh tokens, the API must internally take this into account, instead of issuing a refresh token that is then rejected as unusable at the token endpoint.

More information about this release can be found below.

Download 19.4

For the signature validation: Public GPG key

Standard Connect2id server edition

Apache Tomcat package with Connect2id server 19.4: Connect2id-server.zip

GPG signature: Connect2id-server.zip.asc

SHA-256: ab7d419e88ff95b679acf734e851d9878e395ea1f322781931c0f4fdb05286d0

Connect2id server 19.4 WAR package: c2id.war

GPG signature: c2id.war.asc

SHA-256: 730a1a8358339be26e5af240ece9760761d1ba77bd140a0c480cda28c95027aa

Multi-tenant edition

Apache Tomcat package with Connect2id server 19.4: Connect2id-server-mt.zip

GPG signature: Connect2id-server-mt.zip.asc

SHA-256: a0cf40f39d0c0330da25e6d0abb65840d233da1f70a5526a1dfb33faa2b9ce96

Connect2id server 19.4 WAR package: c2id-mt.war

GPG signature: c2id-mt.war.asc

SHA-256: 7a9d2cbcd47a800bb6274f552410c62d450dd94e789ef53eb1b422c6a3204e37

Questions?

For technical questions about this new release contact Connect2id support. To purchase a production license for the Connect2id server, renew or upgrade your support and updates subscription, email our sales.


Release notes

19.4 (2025-10-28)

  • OAuth 2.0 token exchange (RFC 8693) use cases in which clients exchange DPoP (RFC 9449) access tokens for other access tokens are now fully supported by
    the Connect2id server. Previously, when the Connect2id server received a DPoP access token in the subject_token token request parameter, it was only able to perform introspection of the token, due to the lack of specification text how to pass a DPoP proof for the subject_token and the actor_token in a token exchange grant.

    For an OAuth authorisation server to validate a DPoP access token it must also receive a DPoP proof that includes the ath (access token hash) JWT claim. This kind of DPoP proof was originally specified for protected resource access, not for the token endpoint.

    This Connect2id server release is updated to accept DPoP proofs with the ath claim at the token endpoint for token exchange grants. The DPoP proof is used to validate the binding of a DPoP access token submitted in the subject_token token request parameter. The same DPoP proof is then used to bind the issued access token (as well as refresh token, for a public client). This “dual” use of the DPoP proof header in token exchange grants was informally agreed upon in the OAuth working group in October 2025.

  • Grant handler plugins are now able to find out if the issued access token is going to be bound via mutual TLS (RFC 8705) or DPoP (RFC 9449).

Web API

  • /token

    • When processing OAuth 2.0 token exchange grants (RFC 8705) the Connect2id server is now able to verify the binding of DPoP access tokens (RFC 9449) submitted in the subject_token token request parameter. To verify the binding the Connect2id server must receive a token request with a DPoP proof header that is normally constructed for resource servers - the ath (access token hash) JWT claim must be included in the DPoP proof. If the Connect2id server detects a subject_token that is a locally issued DPoP access token and the DPoP proof header is missing or doesn’t match the token introspection or the token hash, it marks the access token as invalid.

SPI

  • Upgrades the Connect2id server SDK to com.nimbusds:c2id-server-sdk:5.14

    • The GrantHandlerContext receives a new getTokenBindingMethods method that returns the binding method for the token(s) to be issued for the handled OAuth 2.0 grant, such as client credentials or token exchange. The Connect2id server supports the methods MTLS for client X.509 certificate bound tokens (RFC 8705) and DPoP for JWK bound tokens (RFC 9449). Intended to inform authorisation decisions in grant handler plugins.

Resolved issues

  • The Connect2id server must ignore the refresh_token.issue consent parameter in the authorisation code flow when the registered client grant_types does not include refresh_token. Similarly, the server must ignore the rti (refresh token issue) authorisation record parameter when using stored end-user consent in the authorisation code flow and the registered client grant_types does not include refresh_token. Note that a refresh token issued in these circumstances is unusable at the token endpoint, which always performs a check for the presence of refresh_token in the registered client grant_types (issue server / 1125).

  • The Connect2id server must ignore the refresh_token.issue parameter in requests to the direct authorisation web API (/direct-authz/rest/v2) when the registered client grant_types does not include refresh_token. Note that a refresh token issued in this circumstance is unusable at the token endpoint, which always performs a check for the presence of refresh_token in the registered client grant_types (issue server / 1126).

Dependency changes

  • Upgrades to com.nimbusds:c2id-server-sdk:5.14

  • Updates to com.nimbusds:oauth2-oidc-sdk:11.30