Redirect users after login

This commit is contained in:
traxys 2023-08-16 21:46:33 +02:00
parent 2dfaf85eea
commit 85c559cfb1
2 changed files with 65 additions and 8 deletions

View file

@ -5,8 +5,9 @@ use std::{
}; };
use axum::{ use axum::{
extract::{Path, Query, State}, async_trait,
http::StatusCode, extract::{FromRef, FromRequestParts, Path, Query, State},
http::{request::Parts, StatusCode},
response::{Html, IntoResponse, Redirect}, response::{Html, IntoResponse, Redirect},
routing::get, routing::get,
Router, Router,
@ -314,7 +315,6 @@ struct AppState {
jwt_secret: HS256Key, jwt_secret: HS256Key,
db: PgPool, db: PgPool,
oidc: OpenidConnector, oidc: OpenidConnector,
domain: String,
} }
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
@ -379,12 +379,14 @@ struct OidcRedirectParams {
code: String, code: String,
} }
pub static AUTH_COOKIE: &str = "mail_admin_token";
async fn redirected( async fn redirected(
state: State<Arc<AppState>>, state: State<Arc<AppState>>,
Path(id): Path<Uuid>, Path(id): Path<Uuid>,
Query(redirect): Query<OidcRedirectParams>, Query(redirect): Query<OidcRedirectParams>,
jar: CookieJar, jar: CookieJar,
) -> Result<CookieJar, Error> { ) -> Result<(CookieJar, Redirect), Error> {
match state match state
.oidc .oidc
.redirected(id, redirect.state, redirect.code) .redirected(id, redirect.state, redirect.code)
@ -412,20 +414,20 @@ async fn redirected(
let token = state.jwt_secret.authenticate(claims)?; let token = state.jwt_secret.authenticate(claims)?;
let mut cookie = Cookie::named("mail_admin_token"); let mut cookie = Cookie::named(AUTH_COOKIE);
cookie.set_value(token); cookie.set_value(token);
cookie.set_http_only(true); cookie.set_http_only(true);
let mut now = OffsetDateTime::now_utc(); let mut now = OffsetDateTime::now_utc();
now += expire; now += expire;
cookie.set_expires(now); cookie.set_expires(now);
cookie.set_same_site(SameSite::Strict); cookie.set_same_site(SameSite::None);
cookie.set_secure(true); cookie.set_secure(true);
cookie.set_path("/"); cookie.set_path("/");
let jar = jar.add(cookie); let jar = jar.add(cookie);
Ok(jar) Ok((jar, Redirect::to("/")))
} }
Err(e) => { Err(e) => {
tracing::error!("Could not finish OAuth2 flow: {e:?}"); tracing::error!("Could not finish OAuth2 flow: {e:?}");
@ -452,6 +454,42 @@ async fn page_not_found() -> Result<(StatusCode, Html<String>), Error> {
pub static TEMPLATES: Lazy<Tera> = pub static TEMPLATES: Lazy<Tera> =
Lazy::new(|| Tera::new("templates/*.html").expect("Could not generate templates")); Lazy::new(|| Tera::new("templates/*.html").expect("Could not generate templates"));
struct User(Uuid);
#[async_trait]
impl<S> FromRequestParts<S> for User
where
S: Send + Sync,
Arc<AppState>: FromRef<S>,
{
type Rejection = Redirect;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let jar = CookieJar::from_request_parts(parts, state).await.unwrap();
match jar.get(AUTH_COOKIE) {
None => {
tracing::debug!("No auth token");
Err(Redirect::to("/login"))
}
Some(data) => {
let state: Arc<AppState> = State::from_request_parts(parts, state).await.unwrap().0;
let claims = state
.jwt_secret
.verify_token::<NoCustomClaims>(data.value(), None)
.map_err(|_| Redirect::to("/login"))?;
Ok(User(claims.subject.unwrap().parse().unwrap()))
}
}
}
}
async fn home(_: State<Arc<AppState>>, User(_): User) -> Result<Html<String>, Error> {
Ok(Html(TEMPLATES.render("home.html", &global_context())?))
}
#[tokio::main] #[tokio::main]
async fn main() -> color_eyre::Result<()> { async fn main() -> color_eyre::Result<()> {
color_eyre::install()?; color_eyre::install()?;
@ -481,12 +519,12 @@ async fn main() -> color_eyre::Result<()> {
let router = Router::new() let router = Router::new()
.route("/login", get(login)) .route("/login", get(login))
.route("/login/redirect/:id", get(redirected)) .route("/login/redirect/:id", get(redirected))
.route("/", get(home))
.fallback(page_not_found) .fallback(page_not_found)
.with_state(Arc::new(AppState { .with_state(Arc::new(AppState {
db, db,
oidc, oidc,
jwt_secret: config.jwt_secret.0, jwt_secret: config.jwt_secret.0,
domain: config.domain,
})); }));
Ok(axum::Server::bind(&addr) Ok(axum::Server::bind(&addr)

19
templates/home.html Normal file
View file

@ -0,0 +1,19 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ title }}</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"
/>
</head>
<body>
<section class="section">
<div class="container">
<h1 class="title">Mail management</h1>
</div>
</section>
</body>
</html>