Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sgrust01/jwtvault
Highly flexible library to manage and orchestrate JWT workflow
https://github.com/sgrust01/jwtvault
Last synced: about 17 hours ago
JSON representation
Highly flexible library to manage and orchestrate JWT workflow
- Host: GitHub
- URL: https://github.com/sgrust01/jwtvault
- Owner: sgrust01
- Created: 2020-02-15T04:11:59.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-05-25T06:51:06.000Z (over 4 years ago)
- Last Synced: 2024-10-07T02:36:35.509Z (about 1 month ago)
- Language: Rust
- Homepage:
- Size: 163 KB
- Stars: 68
- Watchers: 7
- Forks: 6
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-rust - sgrust01/jwtvault
- awesome-rust-cn - sgrust01/jwtvault
- awesome-rust - sgrust01/jwtvault - Async library to manage and orchestrate JWT workflow (Libraries / Authentication)
- fucking-awesome-rust - sgrust01/jwtvault - Async library to manage and orchestrate JWT workflow (Libraries / Authentication)
- fucking-awesome-rust - sgrust01/jwtvault - Async library to manage and orchestrate JWT workflow (Libraries / Authentication)
README
JWT Vault
Highly flexible library to manage and orchestrate JWT workflow
[![Build Status](https://travis-ci.org/sgrust01/jwtvault.svg?branch=master)](https://travis-ci.org/sgrust01/jwtvault)
[![Build status](https://ci.appveyor.com/api/projects/status/x903r0kr9sivyus2?svg=true)](https://ci.appveyor.com/project/sgrust01/jwtvault)
[![codecov](https://codecov.io/gh/sgrust01/jwtvault/branch/master/graph/badge.svg)](https://codecov.io/gh/sgrust01/jwtvault)
[![Version](https://img.shields.io/badge/rustc-1.39+-blue.svg)](https://blog.rust-lang.org/2019/11/07/Rust-1.39.0.html)
![RepoSize](https://img.shields.io/github/repo-size/sgrust01/jwtvault)
![Crates.io](https://img.shields.io/crates/l/jwtvault)
![Crates.io](https://img.shields.io/crates/v/jwtvault)
![Crates.io](https://img.shields.io/crates/d/jwtvault)
![Contributors](https://img.shields.io/github/contributors/sgrust01/jwtvault)
[![Gitter](https://badges.gitter.im/jwtvault/community.svg)](https://gitter.im/jwtvault/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Say Thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/[email protected])
Examples
|
Website
|
Chat
## TODO
* Add more examples
* Improve coverage## Features
* Manages & Orchestrates JWT for user login, logout & renew
* Option 1: DynamicVault (uses dynamic dispatch but requires considerable less boiler-plate code)
* Option 2: DefaultVault (uses static dispatch but requires considerable more boiler-plate code)
* Async ready
* Easy start
* No un-safe code
* Runs on stable rust
* Uses [Argon](https://en.wikipedia.org/wiki/Argon2) (see [video](https://www.youtube.com/watch?v=Sc3aHMCc4h0&t=339s))
* Library approach (Requires no runtime)
* Supports plugable components
* Invalidates old refresh upon new refresh token renewal
* Invalidates old authentication upon new authentication token renewal
* Cross feeding not allowed
* Handles Thundering herd problem upon authentication token expiry
* Works with any web-server, any password hashing, and any backend ([here](https://github.com/sgrust01/jwtvault_examples))
* Fully functional
[webserver](https://github.com/sgrust01/jwtvault_examples#example-5-webserver)
with [actix](https://github.com/actix/actix)
and [postgres](https://github.com/sfackler/rust-postgres/tree/master/tokio-postgres)## Quickstart
### Prerequisite:
```toml
[dependencies]
jwtvault = "*"
``````shell script
$ curl https://raw.githubusercontent.com/sgrust01/jwtvault/master/generate_certificates.sh > ./generate_certificates.sh
``````shell script
$ chmod 700 generate_certificates.sh && ./generate_certificates.sh
```#### Option 1: DynamicVault
```rust
use std::collections::HashMap;
use std::collections::hash_map::DefaultHasher;use jwtvault::prelude::*;
fn main() {
let hasher = ArgonPasswordHasher::default();
// User: John Doe
let user_john = "john_doe";
let password_for_john = "john";
// Save value 'hashed_password_for_john' to persistent storage
// This is more relevant during user signup/password reset
let hashed_password_for_john = hasher.hash_user_password(user_john, password_for_john).unwrap();// User: Jane Doe
let user_jane = "jane_doe";
let password_for_jane = "jane";
// Save 'hashed_password_for_jane' to persistent storage
// This is more relevant during user signup/password reset
let hashed_password_for_jane = hasher.hash_user_password(user_jane, password_for_jane).unwrap();let mut users = HashMap::new();
// load users and their password from database/somewhere
users.insert(user_john.to_string(), hashed_password_for_john.to_string());
users.insert(user_jane.to_string(), hashed_password_for_jane.to_string());// Setup app users
let login = LoginInfo::new(users);// Initialize vault
let mut vault = DynamicVault::default(Box::new(login));// John needs to login now
let token = block_on(vault.login(
user_john,
password_for_john,
None,
None,
));
let token = token.ok().unwrap();
// When John presents authentication token, it can be used to restore John's session info
let server_refresh_token = block_on(resolve_session_from_client_authentication_token(
&mut vault,
user_john,
token.authentication(),
));
let server_refresh_token = server_refresh_token.ok().unwrap();// server_refresh_token (variable) contains server method which captures client private info
// which never leaves the server
let private_info_about_john = server_refresh_token.server().unwrap();
let key = digest::<_, DefaultHasher>(user_john);
let data_on_server_side = private_info_about_john.get(&key).unwrap();// server_refresh_token (variable) contains client method which captures client public info
// which is also send back to client
assert!(server_refresh_token.client().is_none());// Check out the data on client and server which are public and private respectively
println!("[Private] John Info: {}",
String::from_utf8_lossy(data_on_server_side.as_slice()).to_string());// lets renew authentication token
let new_token = block_on(vault.renew(
user_john,
token.refresh(),
None,
));
let new_token = new_token.ok().unwrap();// When John presents new authentication token it can be used to restore session info
let result = block_on(resolve_session_from_client_authentication_token(
&mut vault,
user_john,
new_token.as_str(),
));
let _ = result.ok().unwrap();
}
```#### Option 2: DefaultVault
```rust
use jwtvault::prelude::*;
use std::collections::HashMap;
use std::collections::hash_map::DefaultHasher;fn main() {
let mut users = HashMap::new();
let loader = CertificateManger::default();
// User: John Doe
let user_john = "john_doe";
let password_for_john = "john";// This should ideally be pre-computed during user sign-up/password reset/change password
let hashed_password_for_john = hash_password_with_argon(
password_for_john,
loader.password_hashing_secret().as_str(),
).unwrap();// User: Jane Doe
let user_jane = "jane_doe";
let password_for_jane = "jane";// This should ideally be pre-computed during user sign-up/password reset/change password
let hashed_password_for_jane = hash_password_with_argon(
password_for_jane,
loader.password_hashing_secret().as_str(),
).unwrap();// load users and their (argon hashed) password from database/somewhere
users.insert(user_john.to_string(), hashed_password_for_john);
users.insert(user_jane.to_string(), hashed_password_for_jane);// Initialize vault
let mut vault = DefaultVault::new(loader, users, false);// John needs to login now
let token = block_on(vault.login(
user_john,
password_for_john,
None,
None,
));
let token = token.ok().unwrap();
// When John presents authentication token, it can be used to restore John's session info
let server_refresh_token = block_on(resolve_session_from_client_authentication_token(
&mut vault,
user_john,
token.authentication(),
));
let server_refresh_token = server_refresh_token.ok().unwrap();// server_refresh_token (variable) contains server method which captures client private info
// which never leaves the server
let private_info_about_john = server_refresh_token.server().unwrap();
let key = digest::<_, DefaultHasher>(user_john);
let data_on_server_side = private_info_about_john.get(&key).unwrap();// server_refresh_token (variable) contains client method which captures client public info
// which is also send back to client
assert!(server_refresh_token.client().is_none());// Check out the data on client and server which are public and private respectively
println!("[Private] John Info: {}",
String::from_utf8_lossy(data_on_server_side.as_slice()).to_string());// lets renew authentication token
let new_token = block_on(vault.renew(
user_john,
token.refresh(),
None,
));
let new_token = new_token.ok().unwrap();// When John presents new authentication token it can be used to restore session info
let result = block_on(resolve_session_from_client_authentication_token(
&mut vault,
user_john,
new_token.as_str(),
));
let _ = result.ok().unwrap();
}
```# Workflows
* To begin use `login` with ___***user***___ and ___***password***___
* Upon successful login is provides user will be provided with JWT pair (authentication/refresh)
* Authentication token is then provided to access any resources
* Refresh token is used to renew an authentication token upon expiry
* Use `resolve_session_from_client_authentication_token` with ___***user***___ and ___***authentication_token***___ to restore user session
* Use `renew` with ___***user***___ and ___***refresh_token***___ to generate new authentication token
* Use `logout` with ___***user***___ and ___***authentication_token***___ will remove all tokens associated with the user
* Use helper `continue_generate_temporary_token` to generate temporary token for user
* Temporary token creates temporary session, and does not corrupt the original session info
* Temporary token cannot be used to login/logout/renew/revoke original session
* Temporary token does not have refresh key (this is intentional), to avoid token refresh
* __**Note:**__ DynamicVault users can directly use instance method `generate_temporary_token`
* __**Typical use-case:**__ Forgot Password
* Use helper `resolve_temporary_session_from_client_authentication_token` to restore user temporary session
* Temporary session are isolated instance, and thus has no fingerprints of the originals session
* __**Typical use-case:**__ Reset Password