Skip to main content

Crate turnkey_jwt_verify

Crate turnkey_jwt_verify 

Source
Expand description

§turnkey_jwt_verify

Core verification utils for JWTs that Turnkey mints. This crate has the generic core verification logic, but does not include support for any specific profiles. Concrete profile support can be found in turnkey_jwt_profiles. Most users are not expected to use this crate directly and should instead use turnkey_jwt_profiles.

§Example

use serde::Deserialize;
use turnkey_jwt_verify::{JwsRules, PinnedKeySet, TimeRules, check_times, unix_now, verify};

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct Claims {
    iat: u64,
    exp: u64,
    sub: String,
}

fn check(jwks: &[u8], token: &str) -> Result<String, Box<dyn std::error::Error>> {
    // In a real service, load the key set once at startup.
    let keys = PinnedKeySet::from_jwks_json(jwks)?;
    let rules = JwsRules::new("application/example+jwt", 4096);
    let claims: Claims = verify(token, &rules, &keys)?.claims()?;
    check_times(claims.iat, claims.exp, unix_now(), &TimeRules::new(5, 300))?;
    Ok(claims.sub)
}

VerifiedJws::claims then parses the payload. The payload must be a JSON object with no nulls and no repeated member names at any depth. A payload that is not JSON is Malformed. A payload that is not a strict object or does not match the struct is BadClaim.

§Defining a claims struct

claims checks only the top level and the rules above. The struct decides the rest, so define it as follows:

  • Derive Deserialize with #[serde(deny_unknown_fields)]. Without it, serde ignores claims the profile does not define.
  • Put #[serde(deny_unknown_fields)] on every nested struct too.
  • Put #[serde(deserialize_with = "turnkey_jwt_verify::object")] on each member whose type is a struct. Serde also accepts a struct as a JSON array of its fields in order, and object rejects that form. A Vec<Inner> or Option<Inner> member is not covered: each Inner still accepts the array form.
  • Use Option<_> with #[serde(default)] for an optional claim.
use serde::Deserialize;
use turnkey_jwt_verify::object;

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct Claims {
    sub: String,
    exp: u64,
    iat: u64,
    #[serde(deserialize_with = "object")]
    request: Request,
    #[serde(default)]
    note: Option<String>,
}

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct Request {
    method: String,
    path: String,
}

Re-exports§

pub use jwks::JwksError;
pub use jwks::KeySource;
pub use jwks::PinnedKeySet;
pub use jwks::VerificationKey;
pub use jwks::thumbprint_p256;

Modules§

b64
Strict base64url helpers (RFC 7515 Section 2).
jwks
Types for parsing and accessing already trusted ES256 verification keys.

Structs§

JwsRules
What verify requires of a token beyond the fixed rules.
ProtectedHeader
The protected header.
TimeRules
Time bounds for check_times.
VerifiedJws
A compact JWS whose header and signature passed verify.

Enums§

Error
A token verification failure.

Constants§

ES256
ES256 alg.

Functions§

check_times
Check iat and exp (NumericDate seconds) against now.
object
Deserialize T from a JSON object only.
strict_json
Parse JSON that is not necessarily an object, with the same strictness as VerifiedJws::claims: no nulls and no repeated member names at any depth.
unix_now
Current Unix time in seconds, or u64::MAX if the clock is before 1970, which makes every token read as expired.
verify
Parse a compact JWS and verify its ES256 signature.