How do I verify a DPoP token? #99
-
What might be the best way to verify DPoP tokens? Are there particular reasons for the absence DPoP validation profile (something like |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 1 reply
-
Too early for DPoP to be considered stable, but all the affordances to be able to do that are already present. Most importantly - a way to verify a key knowing it should be using an embedded public JWK in the JWS header and getting the key's thumbprint
const { payload, key } = jose.JWT.verify(token, jose.JWK.EmbeddedJWK, {
typ: 'dpop+jwt',
algorithms: [/* your acceptable algorithms here */],
complete: true, // to have the embedded public key returned
maxTokenAge: '60s', // to have the iat and its value not being in the future or too far in the past validated
clockTolerance: '5s' // some tolerance for iat not in the future validation
})
assert(typeof payload.jti === 'string' && payload.jti)
assert(typeof payload.htu === 'string' && payload.htu)
assert(typeof payload.htm === 'string' && payload.htm)
// further validate jti to be unique (optional)
// further validate htu to match the request url
// further validate htm to match the request http method
key.thumbprint // is then the actual jkt binding value to be compared with your expected value e.g. parse and then work to validate the binding |
Beta Was this translation helpful? Give feedback.
-
Please consider supporting the library if it provides value to you or your company and this support was of help to you. Supporting the library means, amongst other things, that such support will be available in the future. |
Beta Was this translation helpful? Give feedback.
-
Upgrading to v3, would the following be correct to encode/decode DPoP proofs? Decode: import EmbeddedJWK from 'jose/jwk/embedded'
import jwtVerify from 'jose/jwt/verify'
import calculateThumbprint from 'jose/jwk/thumbprint'
const { payload, protectedHeader } = await jwtVerify(token, EmbeddedJWK, {
typ: 'dpop+jwt',
algorithms: [ /* acceptable digital signature asymmetric cryptographic algorithms */],
maxTokenAge: '60s',
clockTolerance: '5s'
});
assert(typeof payload.jti === 'string' && payload.jti)
assert(typeof payload.htu === 'string' && payload.htu)
assert(typeof payload.htm === 'string' && payload.htm)
// further validate jti to be unique (optional)
// further validate htu to match the request url
// further validate htm to match the request http method
const thumbprint = await calculateThumbprint(protectedHeader.jwk); // is then the actual jkt binding value to be compared with your expected value Encode: import generateKeyPair from 'jose/util/generate_key_pair'
import SignJWT from 'jose/jwt/sign'
const alg = 'ES256';
const { publicKey, privateKey } = await generateKeyPair(alg, { crv: 'P-256' });
const jwt = await new SignJWT({ htm: /* request http method */, htu: /* request http url */ })
.setProtectedHeader({ alg: alg, jwk: publicKey, typ: 'dpop+jwt' })
.setIssuedAt()
.setJti(/* my unique DPoP identifier (uuid) */ )
.sign(privateKey) Assuming one just passes in a JWK containing the private fields ('d' in case of EC; 'd', 'p', 'q', 'dp', 'dq', 'qi' in case of RSA) to a utility function generating the DPoPs, do you have an utility function to shave off those private fields and make the key public and/or a way to indicate the SignJWT that the public key should be embedded (and therefore not manually set it as protected header without the private fields)? |
Beta Was this translation helpful? Give feedback.
-
decode ✅
no, as this is fairly trivial - strip out d, p, q, dp, dq, qi
no. |
Beta Was this translation helpful? Give feedback.
-
Would you maybe consider adding an optional parameter |
Beta Was this translation helpful? Give feedback.
-
no i would not consider that, at most i'm considering a |
Beta Was this translation helpful? Give feedback.
-
DPoP Proofs now have an additional required claim Is there a way in jose to validate those claims? I currently have a function: import { createHash } from "crypto";
import { encode as base64UrlEncode } from "jose/util/base64url";
function isValidAthClaim(
accessToken: string,
athClaim: string
): boolean {
return (
base64UrlEncode(
createHash("sha256").update(Buffer.from(accessToken, "ascii")).digest()
) === athClaim
);
} I am wondering if I could at least reuse some component of JOSE to create the SHA-256 hash of the ASCII encoding of the access token. |
Beta Was this translation helpful? Give feedback.
Too early for DPoP to be considered stable, but all the affordances to be able to do that are already present. Most importantly - a way to verify a key knowing it should be using an embedded public JWK in the JWS header and getting the key's thumbprint