DPoP proof to UserInfo Endpoint is missing 'ath' claim
hjmikkon opened this issue · comments
I'm trying to use the RP against an OP that enforces the use of DPoP access token. The OIDC SSO sequence is going as expected until the UserInfo-call: the OP doesn't accept the request because the mandatory 'ath' -claim is missing from the DPoP proof JWT.
By extracting the DPoP proof, I can see that only the following claims are included in the payload:
- iat
- jti
- htu
- htm
The section 4.2 of the DPoP RFC (9449) says that:
When the DPoP proof is used in conjunction with the presentation of an access token in protected resource access (see [Section 7](https://datatracker.ietf.org/doc/html/rfc9449#protected-resource-access)), the DPoP proof MUST also contain the following claim:
ath:
Hash of the access token. The value MUST be the result of a base64url encoding (as defined in [Section 2](https://rfc-editor.org/rfc/rfc7515#section-2) of [[RFC7515](https://datatracker.ietf.org/doc/html/rfc7515)]) the SHA-256 [[SHS](https://dx.doi.org/10.6028/NIST.FIPS.180-4)] hash of the ASCII encoding of the associated access token's value
For me it sounds like the bug on this library, or am I missing something?
I'm calling the userinfo in the following way (k contains asymmetric key):
const tokenSet = await client!.callback(
`${getDomain()}/auth/callback`,
params, { state }, { 'DPoP': KeyObject.from(k.privateKey) }
);
const user = await client!.userinfo(tokenSet, { 'DPoP': KeyObject.from(k.privateKey) });
Hi @hjmikkon I am unable to reproduce and therefore confirm this report. There's a test confirming ath
claim DPoP Proof presence with the userinfo method.
Hi @panva , thanks for your quick reply.
I'm seeing the following on the OP-side when receiving the userinfo request:
Accept:[application/json]
Accept-Encoding:[gzip, deflate, br]
Authorization:[DPoP eyJraWQiOiJkZWZhdWx0UlNBU2lnbiIs...np0x9R5SSHUEM0RjIAq_TlJViYWByQ]
Connection:[keep-alive]
Content-Type:[null]
dpop:[eyJhbGciOiJFUzM4NCIsInR5cCI6ImRwb3Arand0IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0zODQiLCJ4IjoiRllDTk9hSjNZVEVfMTJkNENVdmdWYlJnUVd5TUoyM1FoVEFZNVdGejBPd2FFRXktT1JzamJXd1VQTnNtSTd1WiIsInkiOiJnRDVXaTUyTTBXMGwzREpkSUp3a0ZveFB2MkVFVmlETVhXZXFTQ3FQOFNBY1ZtaW1uMFRQbkN2TWpaUmZkazBZIn19.eyJpYXQiOjE3MjU4ODAyOTUsImp0aSI6IklxNWFidTJ0Nkp5VGlubWVNSnBuOXJDSE9ERUtUQ0xxRzNZRzNESnNGUjgiLCJodHUiOiJodHRwczovL3Rlc3RvcC5mdW5ldC5maS9pZHAvcHJvZmlsZS9vaWRjL3VzZXJpbmZvIiwiaHRtIjoiR0VUIn0.zAJtdznRZuq1pfPlvLFX4feKk997zYMUOhwWcqYm0YIFe6kp2I9NitgSE69dv6pXtBbEEodCkKRg2TuQtU2L0sfUXeBd2zkeQQqyTxfKoL-nUIBh0Sf5S_S4T3CVZApU]
So it's clear that the DPoP proof payload doesn't have that access token hash, even though the library correctly has added it to the authorization header. Including the DPoP prefix.
I was using this fairly old example as a basis for my tests: https://github.com/franleplant/sso-with-openid
I updated the version in the package.json to 5.6.5 though, so I assume it's using a fresh version of the openid-client. But I may be wrong, this is more or less my first experiment with the Node.js stack..
- "openid-client": "^4.2.0",
+ "openid-client": "^5.6.5",
Can you confirm the installed openid-client version e.g. with cat node_modules/openid-client/package.json | jq '.version'
?
DPoP implementation supports ath
since #407 which was included with release https://github.com/panva/node-openid-client/releases/tag/v4.9.0
That was it, the command you proposed is showing the ancient "4.2.0".
Thanks a lot, I'll find a way to upgrade the version into a fresh one. I assume it's then working as you said.