Skip to content

Instantly share code, notes, and snippets.

@bionicbrian
Created July 20, 2020 14:53
Show Gist options
  • Save bionicbrian/a40d513fa2ed3a5550b923232cd6847d to your computer and use it in GitHub Desktop.
Save bionicbrian/a40d513fa2ed3a5550b923232cd6847d to your computer and use it in GitHub Desktop.
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use rocket::request::{self, FromRequest, Request};
use rocket::Outcome;
use serde::{Deserialize, Serialize};
/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
company: String,
exp: usize,
}
struct ApiToken {
token: jsonwebtoken::TokenData<Claims>,
}
impl ApiToken {
fn token_from_request<'a>(request: &Request) -> Option<jsonwebtoken::TokenData<Claims>> {
let token = match request.headers().get_one("Authorization") {
Some(auth) => {
let parts: Vec<&str> = auth.split(' ').collect();
match parts[..] {
["jwt", jwt] => Some(String::from(jwt)),
_ => None,
}
}
None => None,
};
let api_token = match token {
Some(token) => match decode::<Claims>(
&token,
&DecodingKey::from_secret("secret".as_ref()),
&Validation::default(),
) {
Ok(t) => Some(t),
Err(_) => None,
},
_ => None,
};
api_token
}
}
impl<'a, 'r> FromRequest<'a, 'r> for ApiToken {
type Error = String;
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
let token = ApiToken::token_from_request(request);
match token {
Some(t) => Outcome::Success(ApiToken { token: t }),
None => Outcome::Failure((rocket::http::Status::Unauthorized, "No bueno".to_string())),
}
}
}
#[get("/")]
fn index(token: ApiToken) -> String {
token.token.claims.sub
}
#[get("/token/<name>")]
fn token(name: String) -> String {
let my_claims = Claims {
sub: name,
company: "Cool Things".to_string(),
exp: 1595217600,
};
let api_token = encode(
&Header::default(),
&my_claims,
&EncodingKey::from_secret("secret".as_ref()),
);
match api_token {
Ok(t) => t,
Err(_) => "Oops, nothin'".to_string(),
}
}
fn main() {
rocket::ignite().mount("/", routes![index, token]).launch();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment