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 (see video )
- 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 )
- Fully functional webserver with actix and postgres
Quickstart
Prerequisite:
[dependencies] jwtvault = "*"
$ curl https://raw.githubusercontent.com/sgrust01/jwtvault/master/generate_certificates.sh > ./generate_certificates.sh
$ chmod 700 generate_certificates.sh && ./generate_certificates.sh
Option 1: DynamicVault
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
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
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
共鸣:内容运营方法论
舒扬 / 机械工业出版社 / 2017-5-8 / 59.00
近5年来网络信息量增长了近10倍,信息极度过剩。移动互联网以碎片化、强黏度以及惊人的覆盖率给传统的商业环境带来了巨大的影响,向陈旧的广告、公关、媒体行业展开了深度的冲击。 传统的以渠道为中心的传播思想几近失效,优秀内容成为了各行业最稀缺的资产,这是时代赋予内容生产者的巨大机会。本书作者在多年经验和大量案例研究的基础上,总结出了移动互联网时代的内容运营方法论——共鸣,它将告诉我们如何收获核心粉......一起来看看 《共鸣:内容运营方法论》 这本书的介绍吧!