pub fn verify_assertion(
verifier: Option<&dyn Es256Verifier>,
keys: &AssertionKeys,
assertion: &str,
client_id: &str,
audiences: &[&str],
now: SystemTime,
) -> Result<VerifiedAssertion, AssertionFailure>client-assertion only.Expand description
Verify one RFC 7523 section 3 client assertion.
audiences is what section 3 (3) will accept as naming this server: the caller passes the token
endpoint URL and the issuer identifier. now is the server’s clock.
The ORDER of the checks below is the security property of this function:
algcomes fromkeys, which is the REGISTRATION, and never from the token header. This is the whole of the defence against JWS algorithm confusion, and it is structural rather than a check that could be forgotten:AssertionKeysholds either a secret or public keys, so there is no value an attacker can put in the header that routes an HMAC verification at a public key it already knows.- The SIGNATURE is verified before any claim is read for anything but its own sake. Acting on an unauthenticated claim, even only to produce a better error message, is how a verifier ends up telling an attacker which client ids exist.
- Everything after that is the section 3 claim set, in the section’s own order.
verifier is the ES256 backend, the host’s to choose after 0.9.0: enable jwt-p256 for
crate::jwt::P256Verifier, or pass your own.
It is an Option, and unlike crate::dpop::verify_proof’s it HAS to be, because only ONE of
the two RFC 7523 methods involves a curve at all. private_key_jwt is ES256 and None refuses
it, for that function’s reason: a caller holding no verifier must refuse the credential rather
than verify it leniently. client_secret_jwt is HS256 over the registered secret (RFC 7518
section 3.2), and there is no elliptic curve on that path, no key for a verifier to check and
nothing for a backend to contribute. Taking a verifier by value here made a build with
client-assertion and no ES256 backend refuse a perfectly valid HMAC, which is a refusal no
RFC asks for.
PUBLIC because VerifiedAssertion and AssertionFailure are, and a type no consumer can
obtain is a type that should not have been exported. It is also the other half of
unverified_subject, which has always been public: exposing the “believe nothing” lookup
while hiding the verification it exists to feed left the safe path out of reach.