feat(login): redirect to URL after login
This commit is contained in:
parent
f990708052
commit
66b7a256cf
5 changed files with 35 additions and 7 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1406,6 +1406,7 @@ dependencies = [
|
|||
"redis",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sqlx",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
|
|
|
@ -58,6 +58,7 @@ rand = "0.8.5"
|
|||
rand_core = { version = "0.6.4", features = ["std"] }
|
||||
url = "2.5.3"
|
||||
strum = "0.26.3"
|
||||
serde_urlencoded = "0.7.1"
|
||||
|
||||
[build-dependencies]
|
||||
minijinja-embed = "2.3.1"
|
||||
|
|
8
TODO.md
8
TODO.md
|
@ -10,3 +10,11 @@
|
|||
- [x] Get access token
|
||||
|
||||
- [ ] Support error responses by https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1
|
||||
|
||||
- [ ] Redirect to login when JWT expire
|
||||
- [ ] Add admin panel via API
|
||||
- [ ] Add admin CLI
|
||||
|
||||
- [ ] Support OpenID to use with demo client [oauth2c](https://github.com/cloudentity/oauth2c)
|
||||
|
||||
- .well-known/openid-configuration
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use chrono::{Duration, SecondsFormat, Utc};
|
||||
use log::info;
|
||||
use serde::Deserialize;
|
||||
use axum::{extract::State, http::{HeaderMap, HeaderValue, StatusCode}, response::{Html, IntoResponse}, Extension, Form};
|
||||
use axum::{extract::{Query, State}, http::{HeaderMap, HeaderValue, StatusCode}, response::{Html, IntoResponse}, Extension, Form};
|
||||
use fully_pub::fully_pub;
|
||||
use minijinja::context;
|
||||
|
||||
|
@ -28,9 +28,16 @@ struct LoginForm {
|
|||
|
||||
const DUMMY_PASSWORD_HASH: &str = "$argon2id$v=19$m=19456,t=2,p=1$+06ud2g4uVTI7kUIXjWM4g$6XqwuHt/+xl0d5J4BYKuIbg2acBp6udxMCnmJ6QfceY";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[fully_pub]
|
||||
struct LoginQueryParams {
|
||||
redirect_to: Option<String>
|
||||
}
|
||||
|
||||
pub async fn perform_login(
|
||||
State(app_state): State<AppState>,
|
||||
Extension(renderer): Extension<TemplateRenderer>,
|
||||
Query(query_params): Query<LoginQueryParams>,
|
||||
Form(login): Form<LoginForm>
|
||||
) -> impl IntoResponse {
|
||||
// get user from db
|
||||
|
@ -89,12 +96,15 @@ pub async fn perform_login(
|
|||
let jwt_cookie = format!("minauth_jwt={jwt}; SameSite=Lax; Max-Age={cookie_max_age}");
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert("Set-Cookie", HeaderValue::from_str(&jwt_cookie).unwrap());
|
||||
headers.insert("Location", HeaderValue::from_str(&format!("/me")).unwrap());
|
||||
// TODO: check redirection for arbitrary URL, enforce relative path
|
||||
headers.insert("Location", HeaderValue::from_str(
|
||||
&query_params.redirect_to.unwrap_or(format!("/me"))
|
||||
).unwrap());
|
||||
|
||||
(
|
||||
StatusCode::FOUND,
|
||||
StatusCode::SEE_OTHER,
|
||||
headers,
|
||||
Html("")
|
||||
Html("Logged in. Redirecting you.")
|
||||
).into_response()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use axum::{extract::{Request, State}, http::StatusCode, middleware::Next, response::{Html, IntoResponse, Response}, Extension};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use axum::{extract::{OriginalUri, Query, Request, State}, http::{HeaderMap, HeaderValue, StatusCode}, middleware::Next, response::{Html, IntoResponse, Redirect, Response}, Extension};
|
||||
use axum_extra::extract::CookieJar;
|
||||
|
||||
use crate::{
|
||||
|
@ -36,6 +38,7 @@ pub async fn auth_middleware(
|
|||
|
||||
/// require auth
|
||||
pub async fn enforce_auth_middleware(
|
||||
OriginalUri(original_uri): OriginalUri,
|
||||
token_claims_ext: Option<Extension<UserTokenClaims>>,
|
||||
req: Request,
|
||||
next: Next,
|
||||
|
@ -44,9 +47,14 @@ pub async fn enforce_auth_middleware(
|
|||
Some(_val) => (),
|
||||
None => {
|
||||
// auth is required
|
||||
return Err(
|
||||
(StatusCode::UNAUTHORIZED, Html("Unauthorized: auth is required on this page."))
|
||||
// redirect to login UI
|
||||
let target_url = format!(
|
||||
"/login?{}",
|
||||
serde_urlencoded::to_string(&[
|
||||
("redirect_to", original_uri.to_string())
|
||||
]).expect("To encode URI")
|
||||
);
|
||||
return Err(Redirect::to(&target_url));
|
||||
}
|
||||
};
|
||||
Ok(next.run(req).await)
|
||||
|
|
Loading…
Reference in a new issue