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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffdf8865bac3d9a3bde5bde9088ca431b11f5d37c7a578b8086af77248b76627"
|
checksum = "ffdf8865bac3d9a3bde5bde9088ca431b11f5d37c7a578b8086af77248b76627"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aes-gcm",
|
||||||
|
"base64 0.13.0",
|
||||||
|
"hkdf",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
"rand 0.8.3",
|
||||||
|
"sha2",
|
||||||
|
"subtle",
|
||||||
"time 0.2.26",
|
"time 0.2.26",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
@ -1265,6 +1271,16 @@ version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
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]]
|
[[package]]
|
||||||
name = "hmac"
|
name = "hmac"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
|
|
@ -15,5 +15,5 @@ serde = {version = "1.0", features = ["derive"] }
|
||||||
tenebrous-rpc = { path = "../rpc" }
|
tenebrous-rpc = { path = "../rpc" }
|
||||||
juniper = { git = "https://github.com/graphql-rust/juniper", branch = "master" }
|
juniper = { git = "https://github.com/graphql-rust/juniper", branch = "master" }
|
||||||
juniper_rocket_async = { 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" }
|
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
|
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
|
||||||
|
use rocket::http::{Cookie, CookieJar};
|
||||||
use rocket::response::status::Custom;
|
use rocket::response::status::Custom;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
http::Status,
|
http::Status,
|
||||||
|
@ -25,27 +26,40 @@ struct LoginRequest<'a> {
|
||||||
password: &'a str,
|
password: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rocket::post("/login", data = "<request>")]
|
fn create_token<'a>(
|
||||||
async fn login<'a>(
|
username: &str,
|
||||||
request: Json<LoginRequest<'a>>,
|
expiration: Duration,
|
||||||
config: &State<Config>,
|
secret: &str,
|
||||||
) -> Result<String, Custom<String>> {
|
) -> Result<String, Custom<String>> {
|
||||||
let expiration = Utc::now()
|
let expiration = Utc::now()
|
||||||
.checked_add_signed(Duration::seconds(60))
|
.checked_add_signed(expiration)
|
||||||
.expect("clock went awry")
|
.expect("clock went awry")
|
||||||
.timestamp();
|
.timestamp();
|
||||||
|
|
||||||
let claims = Claims {
|
let claims = Claims {
|
||||||
exp: expiration as usize,
|
exp: expiration as usize,
|
||||||
sub: request.username.to_owned(),
|
sub: username.to_owned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let token = encode(
|
let token = encode(
|
||||||
&Header::default(),
|
&Header::default(),
|
||||||
&claims,
|
&claims,
|
||||||
&EncodingKey::from_secret(config.jwt_secret.as_ref()),
|
&EncodingKey::from_secret(secret.as_bytes()),
|
||||||
)
|
)
|
||||||
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))?;
|
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))?;
|
||||||
|
|
||||||
Ok(token)
|
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