# nickel-jwt-session Experimental jwt-based user session for nickel. Note that the latest version of nickel was released in January 2019 (and this depends on an even slighly older version). This should probably not be used any more, but may possibly be interesting to look at for someone. [![Build Status](https://travis-ci.org/kaj/nickel-jwt-session.svg?branch=master)](https://travis-ci.org/kaj/nickel-jwt-session) [![Crate](https://meritbadge.herokuapp.com/nickel-jwt-session)](https://crates.io/crates/nickel-jwt-session) [![docs](https://docs.rs/nickel-jwt-session/badge.svg)](https://docs.rs/nickel-jwt-session) ## Configuration By default, nickel-jwt-session will store and look for the token in a cookie named "jwt", and the token will expire in 24 hours. The only required argument to the constructor is a private signing key: ```rust extern crate nickel; extern crate nickel_jwt_session; use nickel::Nickel; use nickel_jwt_session::SessionMiddleware; fn main() { let mut server = Nickel::new(); server.utilize(SessionMiddleware::new("My very secret key")); } ``` You can also customize the cookie name: ```rust extern crate nickel; extern crate nickel_jwt_session; use nickel::Nickel; use nickel_jwt_session::{SessionMiddleware, TokenLocation}; fn main() { let mut server = Nickel::new(); server.utilize(SessionMiddleware::new("My very secret key") .using(TokenLocation::Cookie("my-jwt-cookie".to_owned()))); } ``` Or use Authorization: Bearer headers instead of cookies: ```rust extern crate nickel; extern crate nickel_jwt_session; use nickel::Nickel; use nickel_jwt_session::{SessionMiddleware, TokenLocation}; fn main() { let mut server = Nickel::new(); server.utilize(SessionMiddleware::new("My very secret key") .using(TokenLocation::AuthorizationHeader)); } ``` And change the number of seconds the token will be valid for: ```rust extern crate nickel; extern crate nickel_jwt_session; use nickel::Nickel; use nickel_jwt_session::SessionMiddleware; fn main() { let mut server = Nickel::new(); server.utilize(SessionMiddleware::new("My very secret key") .expiration_time(60 * 30)); // 30 min } ``` ## Usage ### Username only If you only want to store a username, you can use the `set_jwt_user()`, `clear_jwt()`, and `authorized_user()` convenience methods. When you have a user that you have authenticated, use the `set_jwt_user()` method to put a new token for that user into the response: ```rust fn login<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> { let authenticated_user = your_authentication_method(req); match authenticated_user { Some(username) => { res.set_jwt_user(username); res.redirect("/") } None => { res.redirect("/login") } } } ``` To check to see if you have an authenticated user, use the `authorized_user()` method: ```rust fn private<'mw>(req: &mut Request, res: Response<'mw>) -> MiddlewareResult<'mw> { match req.authorized_user() { Some(user) => { // Whatever an authorized user is allowed to do }, None => res.error(StatusCode::Forbidden, "Permission denied"), } } ``` And to log a user out, call the `clear_jwt()` method: ```rust fn logout<'mw>(_req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> { res.clear_jwt(); res.redirect("/") } ``` ### Customized claims payload only If you would like to store arbitrary data in the claims payload instead of a username, use the `set_jwt_custom_claims()` and `valid_custom_claims()` methods. The custom claims must be in a `BTreeMap`. Logging out is still done with the `clear_jwt()` method. When you have successfully authenticated, use the `set_jwt_custom_claims()` method to put a new token with the data you include into the response: ```rust use std::collections::BTreeMap; fn login<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> { let authentication_data = your_authentication_method(req); match authentication_data { Some(data) => { let mut d = BTreeMap::new(); d.insert("who".to_owned(), data.who); d.insert("admin".to_owned(), data.admin); res.set_jwt_custom_claims(d); res.redirect("/") } None => { res.redirect("/login") } } } ``` To get the claims out if the token is valid, use the `valid_custom_claims()` method: ```rust fn private<'mw>(req: &mut Request, res: Response<'mw>) -> MiddlewareResult<'mw> { match req.valid_custom_claims() { Some(data) => { // Whatever you do with valid data in the claims }, None => res.error(StatusCode::Forbidden, "Permission denied"), } } ``` And to end a session, call the `clear_jwt()` method: ```rust fn logout<'mw>(_req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> { res.clear_jwt(); res.redirect("/") } ``` ### Username and customized claims payload If you would like to store *both* a username and arbitrary claims data, use the `set_jwt_user_and_custom_claims()` method to add the username and data to the token. You may then use both the `authorized_user()` and `valid_custom_claims()` methods, to get the username and the claims data, respectively. For example: ```rust use std::collections::BTreeMap; fn login<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> { let authentication_data = your_authentication_method(req); match authentication_data { Some(data) => { let mut d = BTreeMap::new(); d.insert("full_name".to_owned(), data.full_name); d.insert("admin".to_owned(), data.admin); res.set_jwt_user_and_custom_claims(data.username, d); res.redirect("/") } None => { res.redirect("/login") } } } ``` To get the username and claims out if the token is valid, use the `authorized_user()` and `valid_custom_claims()` methods: ```rust fn private<'mw>(req: &mut Request, res: Response<'mw>) -> MiddlewareResult<'mw> { match (req.authorized_user(), req.valid_custom_claims()) { (Some(username), Some(data)) => { // Whatever you do with a username and claims data }, (_, _) => res.error(StatusCode::Forbidden, "Permission denied"), } } ``` And to end a session, call the `clear_jwt()` method: ```rust fn logout<'mw>(_req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> { res.clear_jwt(); res.redirect("/") } ``` ## Examples Full working examples can be found in the [examples](examples) directory. Read the [API documentation](https://docs.rs/nickel-jwt-session/). ## License Licensed under either of * Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) * MIT license (http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.