Struct Token

Source
pub struct Token<P, State: MaybeSigned = Unsigned<()>, Fmt: TokenFormat = Compact> { /* private fields */ }
Expand description

A JSON web token, generic over the signing state, format, and payload.

Tokens can change state using the sign, verify, and unverify methods. The format can generally not be changed after constructing the token.

JAWS does not support the general JWS format, only the compact format and the flat format.

§Examples

A few examples are shown below, but the most powerful examples are shown in the examples directory.

§Creating a compact token

use jaws::token::Token;

let token = Token::compact((), ());

This token will have no payload, and no custom headers. To view a debug representation of the token, use the fmt::JWTFormat trait:

use jaws::fmt::JWTFormat;

println!("{}", token.formatted());

§Transitioning a token between states

Tokens start in either the Unsigned or Unverified state. Unsigned tokens are ones constructed locally, but before a signature has been applied. Unverified tokens are ones which have been parsed from a string, but which have not yet been checked.

To transition a token from the Unsigned state to the Signed state, use the Token::sign method:

let key = rsa::pkcs1v15::SigningKey::random(&mut rand::OsRng, 2048).unwrap();
let token = Token::compact((), ());

// The only way to get a signed token is to sign an Unsigned token!
let signed = token.sign::<rsa::pkcs1v15::SigningKey<sha2::Sha256>, rsa::pkcs1v15::Signature>(&key).unwrap();
println!("Token: {}", signed.rendered().unwrap());

Signing often requires specifying the algorithm to use. In the example above, we use RS256, which is the RSA-PKCS1-v1-5 signature algorithm with SHA-256. The algorithm is specified by constraining the type of key when calling Token::sign.

Signed tokens can become unverified ones by discarding the memory of the key used to sign them. This is done with the Token::unverify method:

// We can unverify the token, which discard the memory of the key used to sign it.
let unverified = signed.unverify();

// Unverified tokens still have a signature, but it is no longer considered valid.
println!("Token: {}", unverified.rendered().unwrap());

Tokens can also be transitioned from the Unverified state to the Verified state by checking the signature. This is done with the Token::verify method:

let verified = unverified.verify::<_, rsa::pkcs1v15::Signature>(&verifying_key).unwrap();
println!("Token: {}", verified.rendered().unwrap());

Verification can fail if the signature is invalid, or if the algorithm does not match the one specified in the header. Since keys are strongly typed, it is not possible to make a signature substitution attack using a different key type.

Implementations§

Source§

impl<P, H, Fmt> Token<P, Unsigned<H>, Fmt>
where Fmt: TokenFormat,

Source

pub fn new(header: H, payload: P, fmt: Fmt) -> Self

Create a new token with the given header and payload, in a given format.

See also Token::compact and Token::flat to create a token in a specific format.

Examples found in repository?
examples/acme-new-account.rs (line 66)
36fn main() {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    // RsaPkcs1v15 is really an alias to the digital signature algorithm
48    // implementation in the `rsa` crate, but provided in JAWS to make
49    // it clear which types are compatible with JWTs.
50    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
51
52    let payload = json!({
53      "termsOfServiceAgreed": true,
54      "contact": [
55        "mailto:cert-admin@example.org",
56        "mailto:admin@example.org"
57      ]
58    });
59
60    let header = json!({
61        "nonce": "6S8IqOGY7eL2lsGoTZYifg",
62        "url": "https://example.com/acme/new-account"
63    });
64
65    // Create a token with the default headers, and no custom headers.
66    let mut token = Token::new(payload, header, Compact);
67    // Request that the token header include a JWK field.
68    token.header_mut().key().derived();
69
70    // Sign the token with the algorithm and key we specified above.
71    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
72
73    // Print the token in the ACME example format.
74    println!("{}", signed.formatted());
75}
Source

pub fn empty(header: H, fmt: Fmt) -> Self

Create an empty token with a given header and format.

Source§

impl<P, Fmt> Token<P, Unsigned<()>, Fmt>
where Fmt: TokenFormat,

Source

pub fn blank(fmt: Fmt) -> Self

Create an empty token with no custom header values.

Source

pub fn new_with_payload(payload: P, fmt: Fmt) -> Self

Create a token with a given payload and format, but no custom header values.

Source§

impl<P, H> Token<P, Unsigned<H>, Compact>

Source

pub fn compact(header: H, payload: P) -> Token<P, Unsigned<H>, Compact>

Create a new token with the given header and payload, in the compact format.

See also Token::new and Token::flat to create a token in a specific format.

The compact format is the format with base64url encoded header and payload, separated by a dot, and with the signature appended.

Examples found in repository?
tests/dyn-rsa-key.rs (line 61)
49fn unsigned_token() -> Token<Unsigned<()>> {
50    let claims = Claims {
51        registered: RegisteredClaims {
52            subject: "1234567890".to_string().into(),
53            ..Default::default()
54        },
55        claims: json!({
56            "name": "John Doe",
57            "admin": true,
58        }),
59    };
60
61    let mut token = Token::compact((), claims);
62    *token.header_mut().r#type() = Some("JWT".to_string());
63    token.header_mut().key().derived();
64    token
65}
More examples
Hide additional examples
examples/rfc7515a2.rs (line 66)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
examples/dyn-key.rs (line 55)
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}
Source§

impl<P, H> Token<P, Unsigned<H>, Flat>

Source

pub fn flat(header: H, payload: P) -> Token<P, Unsigned<H>, Flat>

Create a new token with the given header and payload, in the flat format.

See also Token::new and Token::compact to create a token in a specific format.

The flat format is the format with a JSON object containing the header, payload, and signature, all in the same object. It can also include additional JSON data as “unprotected”
headers, which are not signed and cannot be verified.

Source§

impl<P, State: MaybeSigned, Fmt: TokenFormat> Token<P, State, Fmt>

Source

pub fn header(&self) -> HeaderAccess<'_, State::Header, State::HeaderState>

Access to Token header values.

All access is read-only, and the header cannot be modified here, see Token::header_mut for mutable access.

Header fields are accessed as methods on HeaderAccess, and their types will depend on the state of the token. Additionally, the alg field will not be availalbe for unsigned token types.

§Example: No custom headers, only registered headers.
use jaws::token::Token;

let token = Token::compact((), ());
let header = token.header();
assert_eq!(&header.r#type(), &None);
Examples found in repository?
examples/rfc7515a2.rs (line 93)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
More examples
Hide additional examples
examples/dyn-key.rs (line 88)
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}
Source§

impl<P, H, Fmt: TokenFormat> Token<P, Unsigned<H>, Fmt>

Source

pub fn header_mut(&mut self) -> HeaderAccessMut<'_, H, UnsignedHeader>

Mutable access to Token header values

Examples found in repository?
tests/dyn-rsa-key.rs (line 62)
49fn unsigned_token() -> Token<Unsigned<()>> {
50    let claims = Claims {
51        registered: RegisteredClaims {
52            subject: "1234567890".to_string().into(),
53            ..Default::default()
54        },
55        claims: json!({
56            "name": "John Doe",
57            "admin": true,
58        }),
59    };
60
61    let mut token = Token::compact((), claims);
62    *token.header_mut().r#type() = Some("JWT".to_string());
63    token.header_mut().key().derived();
64    token
65}
More examples
Hide additional examples
examples/acme-new-account.rs (line 68)
36fn main() {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    // RsaPkcs1v15 is really an alias to the digital signature algorithm
48    // implementation in the `rsa` crate, but provided in JAWS to make
49    // it clear which types are compatible with JWTs.
50    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
51
52    let payload = json!({
53      "termsOfServiceAgreed": true,
54      "contact": [
55        "mailto:cert-admin@example.org",
56        "mailto:admin@example.org"
57      ]
58    });
59
60    let header = json!({
61        "nonce": "6S8IqOGY7eL2lsGoTZYifg",
62        "url": "https://example.com/acme/new-account"
63    });
64
65    // Create a token with the default headers, and no custom headers.
66    let mut token = Token::new(payload, header, Compact);
67    // Request that the token header include a JWK field.
68    token.header_mut().key().derived();
69
70    // Sign the token with the algorithm and key we specified above.
71    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
72
73    // Print the token in the ACME example format.
74    println!("{}", signed.formatted());
75}
examples/rfc7515a2.rs (line 70)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
examples/dyn-key.rs (line 58)
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}
Source§

impl<P, S, Fmt> Token<P, S, Fmt>
where S: MaybeSigned, Fmt: TokenFormat,

Token serialization and message packing.

Source

pub fn into_format<NewFmt>(self) -> Token<P, S, NewFmt>
where NewFmt: TokenFormat + From<Fmt>,

Convert this token to a new format

Source

pub fn message(&self) -> Result<String, Error>

Get the payload and header of the token, serialized in the compact format, suitable as input into a signature algorithm.

Source

pub fn rendered(&self) -> Result<String, TokenFormattingError>

Get the payload and header of the token, serialized including signature data.

This method is only available when the token is in a signed state.

Examples found in repository?
tests/dyn-rsa-key.rs (line 68)
67fn roundtrip(token: Token<Unverified<()>>) -> Token<Unverified<()>> {
68    let rendered = token.rendered().unwrap();
69    let parsed: Token<Unverified<()>> = rendered.parse().unwrap();
70    assert_eq!(token, parsed);
71    parsed
72}
More examples
Hide additional examples
examples/rfc7515a2.rs (line 87)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
examples/dyn-key.rs (line 74)
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}
Source§

impl<H, Fmt, P> Token<P, Unsigned<H>, Fmt>
where Fmt: TokenFormat,

Source

pub fn payload(&self) -> Option<&P>

Get the payload of the token.

Examples found in repository?
tests/dyn-rsa-key.rs (line 81)
75fn dyn_rsa_verify() {
76    let token = unsigned_token();
77    println!("=== Unsigned Token ===");
78    println!("{}", token.formatted());
79    println!(
80        "Payload: {}",
81        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
82    );
83
84    let signed = token
85        .sign::<_, rsa::pkcs1v15::Signature>(&rsa_signer())
86        .unwrap();
87
88    let unverified = roundtrip(signed.unverify());
89
90    println!("=== Unverified Token ===");
91    println!("{}", unverified.formatted());
92
93    let verified = unverified
94        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
95        .unwrap();
96
97    let unverified = roundtrip(verified.unverify());
98
99    let verified = unverified
100        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
101        .unwrap();
102
103    println!("=== Verified Token ===");
104    println!("{}", verified.formatted());
105}
106
107#[test]
108fn dyn_rsa_sign() {
109    let token = unsigned_token();
110    println!("=== Unsigned Token ===");
111    println!("{}", token.formatted());
112    println!(
113        "Payload: {}",
114        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
115    );
116
117    let signed = token
118        .sign::<_, SignatureBytes>(dyn_signer().as_ref())
119        .unwrap();
120
121    let unverified = roundtrip(signed.unverify());
122
123    println!("=== Unverified Token ===");
124    println!("{}", unverified.formatted());
125
126    let verified = unverified
127        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
128        .unwrap();
129
130    let unverified = roundtrip(verified.unverify());
131
132    let verified = unverified
133        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
134        .unwrap();
135
136    println!("=== Verified Token ===");
137    println!("{}", verified.formatted());
138}
Source

pub fn with_custom_header<H2>(self, header: H2) -> Token<P, Unsigned<H2>, Fmt>

Replace the custom header fields of the token.

Source§

impl<H, Fmt, P> Token<P, Unsigned<H>, Fmt>
where H: Serialize, P: Serialize, Fmt: TokenFormat,

Source

pub fn sign<A, S>( self, algorithm: &A, ) -> Result<Token<P, Signed<H, A, S>, Fmt>, TokenSigningError>
where A: TokenSigner<S> + ?Sized, S: SignatureEncoding,

Sign this token using the given algorithm.

This method consumes the token and returns a new one with the signature attached. Once the signature is attached, the internal fields are no longer mutable (as that would invalidate the signature), but they are still recoverable.

When using this method, you will need to specify the signature encoding type along with the algorithm (i.e. both parameters A and S). The algorithm does not uniquely identify the signature kind, and so it is not possible to infer the signature type from just the algorithm type. For example, all included algorithms also implement signing for the crate::algorithms::SignatureBytes type, which is a raw byte array, suitable for use with any signature (and appropriate for use when you don’t want to statically specify the signature type, see the dyn-key example).

§Example: Signing with a key
let key = rsa::pkcs1v15::SigningKey::random(&mut rand::OsRng, 2048).unwrap();
let token = Token::compact((), ());

// The only way to get a signed token is to sign an Unsigned token!
let signed = token.sign::<rsa::pkcs1v15::SigningKey<sha2::Sha256>, rsa::pkcs1v15::Signature>(&key).unwrap();
println!("Token: {}", signed.rendered().unwrap());

Signing often requires specifying the algorithm to use. In the example above, we use RS256, which is the RSA-PKCS1-v1-5 signature algorithm with SHA-256. The algorithm is specified by constraining the type of key when calling Token::sign.

Examples found in repository?
tests/dyn-rsa-key.rs (line 85)
75fn dyn_rsa_verify() {
76    let token = unsigned_token();
77    println!("=== Unsigned Token ===");
78    println!("{}", token.formatted());
79    println!(
80        "Payload: {}",
81        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
82    );
83
84    let signed = token
85        .sign::<_, rsa::pkcs1v15::Signature>(&rsa_signer())
86        .unwrap();
87
88    let unverified = roundtrip(signed.unverify());
89
90    println!("=== Unverified Token ===");
91    println!("{}", unverified.formatted());
92
93    let verified = unverified
94        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
95        .unwrap();
96
97    let unverified = roundtrip(verified.unverify());
98
99    let verified = unverified
100        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
101        .unwrap();
102
103    println!("=== Verified Token ===");
104    println!("{}", verified.formatted());
105}
106
107#[test]
108fn dyn_rsa_sign() {
109    let token = unsigned_token();
110    println!("=== Unsigned Token ===");
111    println!("{}", token.formatted());
112    println!(
113        "Payload: {}",
114        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
115    );
116
117    let signed = token
118        .sign::<_, SignatureBytes>(dyn_signer().as_ref())
119        .unwrap();
120
121    let unverified = roundtrip(signed.unverify());
122
123    println!("=== Unverified Token ===");
124    println!("{}", unverified.formatted());
125
126    let verified = unverified
127        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
128        .unwrap();
129
130    let unverified = roundtrip(verified.unverify());
131
132    let verified = unverified
133        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
134        .unwrap();
135
136    println!("=== Verified Token ===");
137    println!("{}", verified.formatted());
138}
More examples
Hide additional examples
examples/acme-new-account.rs (line 71)
36fn main() {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    // RsaPkcs1v15 is really an alias to the digital signature algorithm
48    // implementation in the `rsa` crate, but provided in JAWS to make
49    // it clear which types are compatible with JWTs.
50    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
51
52    let payload = json!({
53      "termsOfServiceAgreed": true,
54      "contact": [
55        "mailto:cert-admin@example.org",
56        "mailto:admin@example.org"
57      ]
58    });
59
60    let header = json!({
61        "nonce": "6S8IqOGY7eL2lsGoTZYifg",
62        "url": "https://example.com/acme/new-account"
63    });
64
65    // Create a token with the default headers, and no custom headers.
66    let mut token = Token::new(payload, header, Compact);
67    // Request that the token header include a JWK field.
68    token.header_mut().key().derived();
69
70    // Sign the token with the algorithm and key we specified above.
71    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
72
73    // Print the token in the ACME example format.
74    println!("{}", signed.formatted());
75}
examples/rfc7515a2.rs (line 81)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
examples/dyn-key.rs (line 71)
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}
Source

pub fn sign_randomized<A, S>( self, algorithm: &A, rng: &mut impl CryptoRngCore, ) -> Result<Token<P, Signed<H, A, S>, Fmt>, TokenSigningError>

Available on crate feature rand only.

Sign this token using the given algorithm, and a random number generator.

Source§

impl<H, Fmt, P> Token<P, Unverified<H>, Fmt>
where Fmt: TokenFormat, H: Serialize, P: Serialize,

Source

pub fn verify<A, S>( self, algorithm: &A, ) -> Result<Token<P, Verified<H, A, S>, Fmt>, TokenVerifyingError>

Verify the signature of the token with the given algorithm.

This method consumes the token and returns a new one with the signature verified.

The algorithm must be uniquely specified for verification, otherwise the token could perform a signature downgrade attack.

Examples found in repository?
tests/dyn-rsa-key.rs (line 94)
75fn dyn_rsa_verify() {
76    let token = unsigned_token();
77    println!("=== Unsigned Token ===");
78    println!("{}", token.formatted());
79    println!(
80        "Payload: {}",
81        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
82    );
83
84    let signed = token
85        .sign::<_, rsa::pkcs1v15::Signature>(&rsa_signer())
86        .unwrap();
87
88    let unverified = roundtrip(signed.unverify());
89
90    println!("=== Unverified Token ===");
91    println!("{}", unverified.formatted());
92
93    let verified = unverified
94        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
95        .unwrap();
96
97    let unverified = roundtrip(verified.unverify());
98
99    let verified = unverified
100        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
101        .unwrap();
102
103    println!("=== Verified Token ===");
104    println!("{}", verified.formatted());
105}
106
107#[test]
108fn dyn_rsa_sign() {
109    let token = unsigned_token();
110    println!("=== Unsigned Token ===");
111    println!("{}", token.formatted());
112    println!(
113        "Payload: {}",
114        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
115    );
116
117    let signed = token
118        .sign::<_, SignatureBytes>(dyn_signer().as_ref())
119        .unwrap();
120
121    let unverified = roundtrip(signed.unverify());
122
123    println!("=== Unverified Token ===");
124    println!("{}", unverified.formatted());
125
126    let verified = unverified
127        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
128        .unwrap();
129
130    let unverified = roundtrip(verified.unverify());
131
132    let verified = unverified
133        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
134        .unwrap();
135
136    println!("=== Verified Token ===");
137    println!("{}", verified.formatted());
138}
More examples
Hide additional examples
examples/rfc7515a2.rs (line 119)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
examples/dyn-key.rs (line 97)
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}
Source§

impl<P, H, Alg, Sig, Fmt> Token<P, Signed<H, Alg, Sig>, Fmt>

Source

pub fn unverify(self) -> Token<P, Unverified<H>, Fmt>

Transition the token back into an unverified state.

This method consumes the token and returns a new one, which still includes the signature but which is no longer considered verified.

Examples found in repository?
tests/dyn-rsa-key.rs (line 88)
75fn dyn_rsa_verify() {
76    let token = unsigned_token();
77    println!("=== Unsigned Token ===");
78    println!("{}", token.formatted());
79    println!(
80        "Payload: {}",
81        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
82    );
83
84    let signed = token
85        .sign::<_, rsa::pkcs1v15::Signature>(&rsa_signer())
86        .unwrap();
87
88    let unverified = roundtrip(signed.unverify());
89
90    println!("=== Unverified Token ===");
91    println!("{}", unverified.formatted());
92
93    let verified = unverified
94        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
95        .unwrap();
96
97    let unverified = roundtrip(verified.unverify());
98
99    let verified = unverified
100        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
101        .unwrap();
102
103    println!("=== Verified Token ===");
104    println!("{}", verified.formatted());
105}
106
107#[test]
108fn dyn_rsa_sign() {
109    let token = unsigned_token();
110    println!("=== Unsigned Token ===");
111    println!("{}", token.formatted());
112    println!(
113        "Payload: {}",
114        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
115    );
116
117    let signed = token
118        .sign::<_, SignatureBytes>(dyn_signer().as_ref())
119        .unwrap();
120
121    let unverified = roundtrip(signed.unverify());
122
123    println!("=== Unverified Token ===");
124    println!("{}", unverified.formatted());
125
126    let verified = unverified
127        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
128        .unwrap();
129
130    let unverified = roundtrip(verified.unverify());
131
132    let verified = unverified
133        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
134        .unwrap();
135
136    println!("=== Verified Token ===");
137    println!("{}", verified.formatted());
138}
Source§

impl<H, Fmt, P, Alg, Sig> Token<P, Signed<H, Alg, Sig>, Fmt>

Source

pub fn payload(&self) -> Option<&P>

Get the payload of the token.

Source§

impl<P, H, Alg, Sig, Fmt> Token<P, Verified<H, Alg, Sig>, Fmt>

Source

pub fn unverify(self) -> Token<P, Unverified<H>, Fmt>

Transition the token back into an unverified state.

This method consumes the token and returns a new one, which still includes the signature but which is no longer considered verified.

Examples found in repository?
tests/dyn-rsa-key.rs (line 97)
75fn dyn_rsa_verify() {
76    let token = unsigned_token();
77    println!("=== Unsigned Token ===");
78    println!("{}", token.formatted());
79    println!(
80        "Payload: {}",
81        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
82    );
83
84    let signed = token
85        .sign::<_, rsa::pkcs1v15::Signature>(&rsa_signer())
86        .unwrap();
87
88    let unverified = roundtrip(signed.unverify());
89
90    println!("=== Unverified Token ===");
91    println!("{}", unverified.formatted());
92
93    let verified = unverified
94        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
95        .unwrap();
96
97    let unverified = roundtrip(verified.unverify());
98
99    let verified = unverified
100        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
101        .unwrap();
102
103    println!("=== Verified Token ===");
104    println!("{}", verified.formatted());
105}
106
107#[test]
108fn dyn_rsa_sign() {
109    let token = unsigned_token();
110    println!("=== Unsigned Token ===");
111    println!("{}", token.formatted());
112    println!(
113        "Payload: {}",
114        serde_json::to_string_pretty(&token.payload().unwrap()).unwrap()
115    );
116
117    let signed = token
118        .sign::<_, SignatureBytes>(dyn_signer().as_ref())
119        .unwrap();
120
121    let unverified = roundtrip(signed.unverify());
122
123    println!("=== Unverified Token ===");
124    println!("{}", unverified.formatted());
125
126    let verified = unverified
127        .verify::<_, rsa::pkcs1v15::Signature>(&rsa_verifier())
128        .unwrap();
129
130    let unverified = roundtrip(verified.unverify());
131
132    let verified = unverified
133        .verify::<_, SignatureBytes>(dyn_verifier().as_ref())
134        .unwrap();
135
136    println!("=== Verified Token ===");
137    println!("{}", verified.formatted());
138}
Source§

impl<H, Fmt, P, Alg, Sig> Token<P, Verified<H, Alg, Sig>, Fmt>

Source

pub fn payload(&self) -> Option<&P>

Get the payload of the token.

Examples found in repository?
examples/rfc7515a2.rs (line 127)
36fn main() -> Result<(), Box<dyn std::error::Error>> {
37    // This key is from RFC 7515, Appendix A.2. Provide your own key instead!
38    // The key here is stored as a PKCS#8 PEM file, but you can leverage
39    // RustCrypto to load a variety of other formats.
40    let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(concat!(
41        env!("CARGO_MANIFEST_DIR"),
42        "/examples/rfc7515a2.pem"
43    )))
44    .unwrap();
45
46    // We will sign the JWT with the RS256 algorithm: RSA with SHA-256.
47    let alg = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
48
49    // Claims can combine registered and custom fields. The claims object
50    // can be any type which implements [serde::Serialize].
51    let claims: Claims<serde_json::Value, (), String, (), ()> = Claims {
52        registered: RegisteredClaims {
53            subject: "1234567890".to_string().into(),
54            ..Default::default()
55        },
56        claims: json!({
57            "name": "John Doe",
58            "admin": true,
59        }),
60    };
61
62    // Create a token with the default headers, and no custom headers.
63    // The unit type can be used here because it implements [serde::Serialize],
64    // but a custom type could be passed if we wanted to have custom header
65    // fields.
66    let mut token = Token::compact((), claims);
67
68    // We can modify the headers freely before signing the JWT. In this case,
69    // we provide the `typ` header, which is optional in the JWT spec.
70    *token.header_mut().r#type() = Some("JWT".to_string());
71
72    // We can also ask that some fields be derived from the signing key, for example,
73    // this will derive the JWK field in the header from the signing key.
74    token.header_mut().key().derived();
75
76    println!("=== Initial JWT ===");
77    // Initially the JWT has no defined signature:
78    println!("{}", token.formatted());
79
80    // Sign the token with the algorithm, and print the result.
81    let signed = token.sign::<_, rsa::pkcs1v15::Signature>(&alg).unwrap();
82
83    println!("=== Signed JWT ===");
84
85    println!("JWT:");
86    println!("{}", signed.formatted());
87    println!("Token: {}", signed.rendered().unwrap());
88
89    // We can't modify the token after signing it (that would change the signature)
90    // but we can access fields and read from them:
91    println!(
92        "Type: {:?}, Algorithm: {:?}",
93        signed.header().r#type(),
94        signed.header().algorithm(),
95    );
96
97    // We can also verify tokens.
98    let token: Token<Claims<serde_json::Value>, Unverified<()>, Compact> =
99        signed.rendered().unwrap().parse().unwrap();
100
101    println!("=== Parsed JWT ===");
102
103    // Unverified tokens can be printed for debugging, but there is deliberately
104    // no access to the payload, only to the header fields.
105    println!("JWT:");
106    println!("{}", token.formatted());
107
108    // We can use the JWK to verify that the token is signed with the correct key.
109    let hdr = token.header();
110    let jwk = hdr.key().unwrap();
111    let key = rsa::RsaPublicKey::from_jwk(jwk).unwrap();
112
113    assert_eq!(&key, alg.verifying_key().as_ref());
114    println!("=== Verification === ");
115    let alg: rsa::pkcs1v15::VerifyingKey<Sha256> = alg.verifying_key();
116
117    // We can't access the claims until we verify the token.
118    let verified = token
119        .verify::<_, jaws::algorithms::SignatureBytes>(&alg)
120        .unwrap();
121
122    println!("=== Verified JWT ===");
123    println!("JWT:");
124    println!("{}", verified.formatted());
125    println!(
126        "Payload: \n{}",
127        serde_json::to_string_pretty(&verified.payload()).unwrap()
128    );
129
130    Ok(())
131}
More examples
Hide additional examples
examples/dyn-key.rs (line 126)
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}

Trait Implementations§

Source§

impl<P: Clone, State: Clone + MaybeSigned, Fmt: Clone + TokenFormat> Clone for Token<P, State, Fmt>

Source§

fn clone(&self) -> Token<P, State, Fmt>

Returns a duplicate of the value. Read more
1.0.0 · Source§

const fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<P: Debug, State: Debug + MaybeSigned, Fmt: Debug + TokenFormat> Debug for Token<P, State, Fmt>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P, H, Fmt> FromStr for Token<P, Unverified<H>, Fmt>

Source§

type Err = TokenParseError

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
Source§

impl<P, S, Fmt> JWTFormat for Token<P, S, Fmt>

Available on crate feature fmt only.
Source§

fn fmt<W: Write>(&self, f: &mut IndentWriter<'_, W>) -> Result

Write this format at the current indentation.
Source§

fn fmt_indented<W: Write>(&self, f: &mut IndentWriter<'_, W>) -> Result

Write this format at an indented level one greater than the current level. Read more
Source§

fn fmt_indented_skip_first<W: Write>( &self, f: &mut IndentWriter<'_, W>, ) -> Result

Write this format at an indented level one greater than the current level, but don’t indent the first line.
Source§

fn formatted(&self) -> JWTFormatted<'_, Self>

Return a formatting proxy which will use the ACME format when used with std::fmt::Display.
Source§

impl<P, H, Fmt> JWTFormat for Token<P, Unsigned<H>, Fmt>
where H: Serialize, P: Serialize, Fmt: TokenFormat,

Available on crate feature fmt only.
Source§

fn fmt<W: Write>(&self, f: &mut IndentWriter<'_, W>) -> Result

Write this format at the current indentation.
Source§

fn fmt_indented<W: Write>(&self, f: &mut IndentWriter<'_, W>) -> Result

Write this format at an indented level one greater than the current level. Read more
Source§

fn fmt_indented_skip_first<W: Write>( &self, f: &mut IndentWriter<'_, W>, ) -> Result

Write this format at an indented level one greater than the current level, but don’t indent the first line.
Source§

fn formatted(&self) -> JWTFormatted<'_, Self>

Return a formatting proxy which will use the ACME format when used with std::fmt::Display.
Source§

impl<P: PartialEq, State: PartialEq + MaybeSigned, Fmt: PartialEq + TokenFormat> PartialEq for Token<P, State, Fmt>

Source§

fn eq(&self, other: &Token<P, State, Fmt>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<P, S> Serialize for Token<P, S, Flat>

Source§

fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where Ser: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<P, S, U> Serialize for Token<P, S, FlatUnprotected<U>>

Source§

fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where Ser: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<P: Eq, State: Eq + MaybeSigned, Fmt: Eq + TokenFormat> Eq for Token<P, State, Fmt>

Source§

impl<P, State: MaybeSigned, Fmt: TokenFormat> StructuralPartialEq for Token<P, State, Fmt>

Auto Trait Implementations§

§

impl<P, State, Fmt> Freeze for Token<P, State, Fmt>
where State: Freeze, Fmt: Freeze, P: Freeze,

§

impl<P, State, Fmt> RefUnwindSafe for Token<P, State, Fmt>
where State: RefUnwindSafe, Fmt: RefUnwindSafe, P: RefUnwindSafe,

§

impl<P, State, Fmt> Send for Token<P, State, Fmt>
where State: Send, Fmt: Send, P: Send,

§

impl<P, State, Fmt> Sync for Token<P, State, Fmt>
where State: Sync, Fmt: Sync, P: Sync,

§

impl<P, State, Fmt> Unpin for Token<P, State, Fmt>
where State: Unpin, Fmt: Unpin, P: Unpin,

§

impl<P, State, Fmt> UnwindSafe for Token<P, State, Fmt>
where State: UnwindSafe, Fmt: UnwindSafe, P: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> ErasedDestructor for T
where T: 'static,