Skip to content

suransea/jwt-rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jwt-rust

jwts jwts jwts jwts

jwt

A rust implementation of JSON Web Tokens.

Examples

Encode

use jwts::{Claims, jws};
use jwts::jws::Header;
use jwts::jws::alg::HS256;

let claims = Claims {
    iss: Some("sea".to_owned()),
    ..Default::default()
};
jws::encode::<HS256>(Header::default(), &claims, b"secret").unwrap();

Decode

use jwts::{Claims, jws};
use jwts::jws::{Header, NoVerify, Token, VerifyWith};
use jwts::jws::alg::HS256;

let claims = Claims::default();
let token = jws::encode::<HS256>(Header::default(), &claims, b"secret").unwrap();

let Token {..} = jws::decode::<Claims>(&token, NoVerify).unwrap(); // no verify
let Token {..} = jws::decode::<Claims>(&token, VerifyWith::<HS256>(b"secret")).unwrap(); // verify with algorithm and key

Validate Claims

use std::collections::HashMap;
use std::time::{Duration, SystemTime};
use jwts::Claims;
use jwts::validate::{ExpectAud, ExpectIss, ExpectJti, ExpectSub, ExpiredTime, IssuedAtTime, NotBeforeTime, Validate};

let claims = Claims {
    iss: Some("sea".to_owned()),
    sub: Some("subject".to_owned()),
    aud: Some("audience".to_owned()),
    jti: Some("id".to_owned()),
    ..Default::default()
};
let claims = claims
    .issued_now()
    .expired_in(Duration::from_secs(1))
    .not_before(SystemTime::now());

claims.validate(IssuedAtTime).unwrap();
claims.validate(NotBeforeTime).unwrap();
claims.validate(ExpiredTime).unwrap();
claims.validate(ExpectIss("sea")).unwrap();
claims.validate(ExpectSub("subject")).unwrap();
claims.validate(ExpectAud("audience")).unwrap();
claims.validate(ExpectJti("id")).unwrap();

// builtin validation works with any `Serialize` type:
let claims = HashMap::from([("iss", "sea")]);
claims.validate(ExpectIss("sea")).unwrap();

Custom Claims Type

use std::collections::HashMap;
use serde_derive::{Deserialize, Serialize};
use jwts::jws;
use jwts::jws::{Header, Token, VerifyWith};
use jwts::jws::alg::HS256;

#[derive(Debug, Serialize, Deserialize)]
struct CustomClaims {
    iss: String,
}

let claims = CustomClaims {
    iss: "sea".to_owned(),
};
let token = jws::encode::<HS256>(Header::default(), &claims, b"secret").unwrap();
let Token {..} = jws::decode::<CustomClaims>(&token, VerifyWith::<HS256>(b"secret")).unwrap();

// Or use a map directly
let claims = HashMap::from([("iss", "sea")]);
let Token {..} = jws::decode::<HashMap<String, String>>(&token, VerifyWith::<HS256>(b"secret")).unwrap();

Custom Algorithm

use jwts::{Claims, Error, jws};
use jwts::jws::{Algorithm, Header, Token, VerifyWith};

pub struct None;

impl Algorithm for None {
    type SignKey = ();
    type VerifyKey = ();

    fn name() -> &'static str {
        "None"
    }

    fn sign(data: impl AsRef<[u8]>, key: &Self::SignKey) -> Result<Vec<u8>, Error> {
        Ok([].into())
    }

    fn verify(data: impl AsRef<[u8]>, sig: impl AsRef<[u8]>, key: &Self::VerifyKey) -> Result<(), Error> {
        sig.as_ref().is_empty().then_some(()).ok_or(Error::InvalidSignature)
    }
}

let claims = Claims::default();
let token = jws::encode::<None>(Header::default(), &claims, &()).unwrap();
let Token {..} = jws::decode::<Claims>(&token, VerifyWith::<None>(&())).unwrap();

Custom Verification

use jwts::{Claims, Error, jws};
use jwts::jws::{Algorithm, Header, Token, Verify};
use jwts::jws::alg::HS256;

pub struct CustomVerify;

impl Verify<Claims> for CustomVerify {
    fn verify(&self, f2s: &str, signature: &[u8], header: &Header, payload: &Claims) -> Result<(), Error> {
        HS256::verify(f2s, signature, b"secret")
    }
}

let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzZWEifQ.L0DLtDjydcSK-c0gTyOYbmUQ_LUCZzqAGCINn2OLhFs";
let Token {..} = jws::decode::<Claims>(&token, CustomVerify).unwrap();

Custom Claims Validation

use jwts::Claims;
use jwts::validate::{Validate, Validation};

pub struct CustomValidation;

impl Validation<Claims> for CustomValidation {
    type Error = ();

    fn validate(&self, claims: &Claims) -> Result<(), Self::Error> {
        claims.aud.is_some().then_some(()).ok_or(())
    }
}

let claims = Claims {
    aud: Some("audience".to_owned()),
    ..Default::default()
};
claims.validate(CustomValidation).unwrap();

Algorithms

Sign and verify using crate aws-lc-rs.

  • HS256 - HMAC using SHA-256
  • HS384 - HMAC using SHA-384
  • HS512 - HMAC using SHA-512
  • RS256 - RSASSA-PKCS1-v1_5 using SHA-256
  • RS384 - RSASSA-PKCS1-v1_5 using SHA-384
  • RS512 - RSASSA-PKCS1-v1_5 using SHA-512
  • ES256 - ECDSA using P-256 and SHA-256
  • ES384 - ECDSA using P-384 and SHA-384
  • ES512 - ECDSA using P-521 and SHA-512
  • PS256 - RSASSA-PSS using SHA-256 and MGF1 with SHA-256
  • PS384 - RSASSA-PSS using SHA-384 and MGF1 with SHA-384
  • PS512 - RSASSA-PSS using SHA-512 and MGF1 with SHA-512

Migrate from 0.2

<= 0.2 >= 0.4
Token::sign jws::encode
Token::decode jws::decode with NoVerify
Token::verify_with_key jws::decode with VerifyWith
Token::verify_with_key_resolver jws::decode with custom verify
Token::validate_claims Validate::validate

More

RFC 7519 JSON Web Token (JWT)

RFC 7515 JSON Web Signature (JWS)

RFC 7518 JSON Web Algorithms (JWA)

License

Apache 2.0 License

About

Rust implementation of JSON Web Tokens

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages