160 lines
5.1 KiB
Markdown
160 lines
5.1 KiB
Markdown
# jsonwebtoken
|
|
|
|
[![Build Status](https://travis-ci.org/Keats/jsonwebtoken.svg)](https://travis-ci.org/Keats/jsonwebtoken)
|
|
|
|
[API documentation on docs.rs](https://docs.rs/jsonwebtoken/)
|
|
|
|
## Installation
|
|
Add the following to Cargo.toml:
|
|
|
|
```toml
|
|
jsonwebtoken = "7"
|
|
serde = {version = "1.0", features = ["derive"] }
|
|
```
|
|
|
|
## How to use
|
|
Complete examples are available in the examples directory: a basic one and one with a custom header.
|
|
|
|
In terms of imports and structs:
|
|
```rust
|
|
use serde::{Serialize, Deserialize};
|
|
use jsonwebtoken::{encode, decode, Header, Algorithm, Validation};
|
|
|
|
/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
struct Claims {
|
|
sub: String,
|
|
company: String,
|
|
exp: usize,
|
|
}
|
|
```
|
|
|
|
### Header
|
|
The default algorithm is HS256.
|
|
|
|
```rust
|
|
let token = encode(&Header::default(), &my_claims, "secret".as_ref())?;
|
|
```
|
|
|
|
#### Custom headers & changing algorithm
|
|
All the parameters from the RFC are supported but the default header only has `typ` and `alg` set.
|
|
If you want to set the `kid` parameter or change the algorithm for example:
|
|
|
|
```rust
|
|
let mut header = Header::new(Algorithm::HS512);
|
|
header.kid = Some("blabla".to_owned());
|
|
let token = encode(&header, &my_claims, "secret".as_ref())?;
|
|
```
|
|
Look at `examples/custom_header.rs` for a full working example.
|
|
|
|
### Encoding
|
|
|
|
```rust
|
|
// HS256
|
|
let token = encode(&Header::default(), &my_claims, "secret".as_ref())?;
|
|
// RSA
|
|
let token = encode(&Header::new(Algorithm::RS256), &my_claims, include_str!("privkey.pem"))?;
|
|
```
|
|
Encoding a JWT takes 3 parameters:
|
|
|
|
- a header: the `Header` struct
|
|
- some claims: your own struct
|
|
- a key
|
|
|
|
When using HS256, HS2384 or HS512, the key is always a shared secret like in the example above. When using
|
|
RSA/EC, the key should always be the content of the private key in the PEM format.
|
|
|
|
### Decoding
|
|
|
|
```rust
|
|
let token = decode::<Claims>(&token, "secret".as_ref(), &Validation::default())?;
|
|
// token is a struct with 2 fields: `header` and `claims` and `claims` is your own struct.
|
|
```
|
|
`decode` can error for a variety of reasons:
|
|
|
|
- the token or its signature is invalid
|
|
- the token had invalid base64
|
|
- validation of at least one reserved claim failed
|
|
|
|
As with encoding, when using HS256, HS2384 or HS512, the key is always a shared secret like in the example above. When using
|
|
RSA/EC, the key should always be the content of the public key in the PEM format.
|
|
|
|
In some cases, for example if you don't know the algorithm used or need to grab the `kid`, you can decode only the header:
|
|
|
|
```rust
|
|
let header = decode_header(&token)?;
|
|
```
|
|
|
|
This does not perform any signature verification/validations on the token so it could have been tampered with.
|
|
|
|
You can also decode a token using the public key components of a RSA key in base64 format.
|
|
The main use-case is for JWK where your public key is a JSON format like so:
|
|
|
|
```json
|
|
{
|
|
"kty":"RSA",
|
|
"e":"AQAB",
|
|
"kid":"6a7a119f-0876-4f7e-8d0f-bf3ea1391dd8",
|
|
"n":"yRE6rHuNR0QbHO3H3Kt2pOKGVhQqGZXInOduQNxXzuKlvQTLUTv4l4sggh5_CYYi_cvI-SXVT9kPWSKXxJXBXd_4LkvcPuUakBoAkfh-eiFVMh2VrUyWyj3MFl0HTVF9KwRXLAcwkREiS3npThHRyIxuy0ZMeZfxVL5arMhw1SRELB8HoGfG_AtH89BIE9jDBHZ9dLelK9a184zAf8LwoPLxvJb3Il5nncqPcSfKDDodMFBIMc4lQzDKL5gvmiXLXB1AGLm8KBjfE8s3L5xqi-yUod-j8MtvIj812dkS4QMiRVN_by2h3ZY8LYVGrqZXZTcgn2ujn8uKjXLZVD5TdQ"
|
|
}
|
|
```
|
|
|
|
```rust
|
|
let token = decode_rsa_components::<Claims>(&token, jwk["n"], jwk["e"], &Validation::new(Algorithm::RS256))?;
|
|
// token is a struct with 2 fields: `header` and `claims` and `claims` is your own struct.
|
|
```
|
|
|
|
### Convertion .der to .pem
|
|
|
|
You can use openssl for that:
|
|
|
|
```bash
|
|
openssl rsa -inform DER -outform PEM -in mykey.der -out mykey.pem
|
|
```
|
|
|
|
|
|
#### Validation
|
|
This library validates automatically the `exp` claim. `nbf` is also validated if present. You can also validate the `sub`, `iss` and `aud` but
|
|
those require setting the expected value in the `Validation` struct.
|
|
|
|
Since validating time fields is always a bit tricky due to clock skew,
|
|
you can add some leeway to the `iat`, `exp` and `nbf` validation by setting the `leeway` field.
|
|
|
|
Last but not least, you will need to set the algorithm(s) allowed for this token if you are not using `HS256`.
|
|
|
|
```rust
|
|
use jsonwebtoken::{Validation, Algorithm};
|
|
|
|
// Default validation: the only algo allowed is HS256
|
|
let validation = Validation::default();
|
|
// Quick way to setup a validation where only the algorithm changes
|
|
let validation = Validation::new(Algorithm::HS512);
|
|
// Adding some leeway (in seconds) for exp and nbf checks
|
|
let mut validation = Validation {leeway: 60, ..Default::default()};
|
|
// Checking issuer
|
|
let mut validation = Validation {iss: Some("issuer".to_string()), ..Default::default()};
|
|
// Setting audience
|
|
let mut validation = Validation::default();
|
|
validation.set_audience(&"Me"); // string
|
|
validation.set_audience(&["Me", "You"]); // array of strings
|
|
```
|
|
|
|
## Algorithms
|
|
This library currently supports the following:
|
|
|
|
- HS256
|
|
- HS384
|
|
- HS512
|
|
- RS256
|
|
- RS384
|
|
- RS512
|
|
- PS256
|
|
- PS384
|
|
- PS512
|
|
- ES256
|
|
- ES384
|
|
|
|
### RSA & ECDSA
|
|
By default, the `encode`/`decode` functions takes the PEM format since it is the most common.
|
|
RSA can also use the public key components modulus/exponent in base64 format for decoding.
|