dyn_key/
dyn-key.rs

1use jaws::algorithms::SignatureBytes;
2use jaws::algorithms::TokenSigner;
3use jaws::algorithms::TokenVerifier;
4use jaws::key::DeserializeJWK;
5use jaws::token::Unverified;
6use jaws::Compact;
7use jaws::JWTFormat;
8use jaws::Token;
9use jaws::{Claims, RegisteredClaims};
10use rsa::pkcs8::DecodePrivateKey;
11use serde_json::json;
12use sha2::Sha256;
13
14fn type_name_of_val<T>(_: &T) -> &'static str {
15    std::any::type_name::<T>()
16}
17
18fn main() -> Result<(), Box<dyn std::error::Error>> {
19    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
20    // The key here is stored as a PKCS#8 PEM file, but you can leverage
21    // RustCrypto to load a variety of other formats.
22    let signing_key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
23        env!("CARGO_MANIFEST_DIR"),
24        "/examples/rfc7515a2.pem"
25    )))
26    .unwrap();
27    let verify_key: rsa::pkcs1v15::VerifyingKey<Sha256> =
28        rsa::pkcs1v15::VerifyingKey::new(signing_key.to_public_key());
29
30    // We will sign the JWT with a type-erased algorithm, and use a type-erased
31    // verifier to verify it. This allows you to use a set of verifiers which
32    // are not known at compile time.
33    let dyn_signing_key: Box<dyn TokenSigner<SignatureBytes>> = Box::new(
34        rsa::pkcs1v15::SigningKey::<Sha256>::new(signing_key.clone()),
35    );
36    let dyn_verify_key: Box<dyn TokenVerifier<SignatureBytes>> = Box::new(verify_key.clone());
37
38    // Claims can combine registered and custom fields. The claims object
39    // can be any type which implements [serde::Serialize].
40    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
41        registered: RegisteredClaims {
42            subject: "1234567890".to_string().into(),
43            ..Default::default()
44        },
45        claims: json!({
46            "name": "John Doe",
47            "admin": true,
48        }),
49    };
50
51    // Create a token with the default headers, and no custom headers.
52    // The unit type can be used here because it implements [serde::Serialize],
53    // but a custom type could be passed if we wanted to have custom header
54    // fields.
55    let mut token = Token::compact((), claims);
56    // We can modify the headers freely before signing the JWT. In this case,
57    // we provide the `typ` header, which is optional in the JWT spec.
58    *token.header_mut().r#type() = Some("JWT".to_string());
59
60    // We can also ask that some fields be derived from the signing key, for example,
61    // this will derive the JWK field in the header from the signing key.
62    token.header_mut().key().derived();
63
64    println!("=== Initial JWT ===");
65
66    // Initially the JWT has no defined signature:
67    println!("{}", token.formatted());
68
69    // Sign the token with the algorithm, and print the result.
70    let signed = token
71        .sign::<_, SignatureBytes>(dyn_signing_key.as_ref())
72        .unwrap();
73
74    let rendered = signed.rendered().unwrap();
75
76    // We can also verify tokens.
77    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
78        rendered.parse().unwrap();
79
80    println!("=== Parsed JWT ===");
81
82    // Unverified tokens can be printed for debugging, but there is deliberately
83    // no access to the payload, only to the header fields.
84    println!("JWT:");
85    println!("{}", token.formatted());
86
87    // We can use the JWK to verify that the token is signed with the correct key.
88    let hdr = token.header();
89    let jwk = hdr.key().unwrap();
90    let key: rsa::pkcs1v15::VerifyingKey<Sha256> =
91        rsa::pkcs1v15::VerifyingKey::new(rsa::RsaPublicKey::from_jwk(jwk).unwrap());
92
93    println!("=== Verification === ");
94    // Check it against the verified key
95    token
96        .clone()
97        .verify::<_, rsa::pkcs1v15::Signature>(&verify_key)
98        .unwrap();
99    println!(
100        "Verified with verify key (typed): {}",
101        type_name_of_val(&verify_key)
102    );
103
104    // Check it against the verified key
105    let verified = token
106        .clone()
107        .verify::<_, SignatureBytes>(dyn_verify_key.as_ref())
108        .unwrap();
109    println!(
110        "Verified with dyn verify key: {}",
111        type_name_of_val(&dyn_verify_key)
112    );
113
114    // Check it against its own JWT
115    token
116        .clone()
117        .verify::<_, rsa::pkcs1v15::Signature>(&key)
118        .unwrap();
119    println!("Verified with JWK");
120
121    println!("=== Verified JWT ===");
122    println!("JWT:");
123    println!("{}", verified.formatted());
124    println!(
125        "Payload: \n{}",
126        serde_json::to_string_pretty(&verified.payload()).unwrap()
127    );
128
129    Ok(())
130}