Also create a refresh token, and store it as HTTP only cookie.
This commit is contained in:
parent
9a5d765d9b
commit
d94451897c
|
@ -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"
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue