Also create a refresh token, and store it as HTTP only cookie.

This commit is contained in:
projectmoon 2021-06-09 15:41:57 +00:00
parent 9a5d765d9b
commit d94451897c
3 changed files with 38 additions and 8 deletions

16
Cargo.lock generated
View File

@ -501,7 +501,13 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf8865bac3d9a3bde5bde9088ca431b11f5d37c7a578b8086af77248b76627"
dependencies = [
"aes-gcm",
"base64 0.13.0",
"hkdf",
"percent-encoding",
"rand 0.8.3",
"sha2",
"subtle",
"time 0.2.26",
"version_check",
]
@ -1265,6 +1271,16 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hkdf"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
dependencies = [
"digest",
"hmac",
]
[[package]]
name = "hmac"
version = "0.10.1"

View File

@ -15,5 +15,5 @@ serde = {version = "1.0", features = ["derive"] }
tenebrous-rpc = { path = "../rpc" }
juniper = { git = "https://github.com/graphql-rust/juniper", branch = "master" }
juniper_rocket_async = { git = "https://github.com/graphql-rust/juniper", branch = "master" }
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", features = ["json"] }
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", features = ["json", "secrets"] }
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }

View File

@ -1,6 +1,7 @@
use crate::config::Config;
use chrono::{Duration, Utc};
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use rocket::http::{Cookie, CookieJar};
use rocket::response::status::Custom;
use rocket::{
http::Status,
@ -25,27 +26,40 @@ struct LoginRequest<'a> {
password: &'a str,
}
#[rocket::post("/login", data = "<request>")]
async fn login<'a>(
request: Json<LoginRequest<'a>>,
config: &State<Config>,
fn create_token<'a>(
username: &str,
expiration: Duration,
secret: &str,
) -> Result<String, Custom<String>> {
let expiration = Utc::now()
.checked_add_signed(Duration::seconds(60))
.checked_add_signed(expiration)
.expect("clock went awry")
.timestamp();
let claims = Claims {
exp: expiration as usize,
sub: request.username.to_owned(),
sub: username.to_owned(),
};
let token = encode(
&Header::default(),
&claims,
&EncodingKey::from_secret(config.jwt_secret.as_ref()),
&EncodingKey::from_secret(secret.as_bytes()),
)
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))?;
Ok(token)
}
#[rocket::post("/login", data = "<request>")]
async fn login(
request: Json<LoginRequest<'_>>,
config: &State<Config>,
cookies: &CookieJar<'_>,
) -> Result<String, Custom<String>> {
let token = create_token(request.username, Duration::minutes(1), &config.jwt_secret)?;
let refresh_token = create_token(request.username, Duration::weeks(1), &config.jwt_secret)?;
cookies.add_private(Cookie::new("refresh_token", refresh_token));
Ok(token)
}