Redirect users after login
This commit is contained in:
parent
2dfaf85eea
commit
85c559cfb1
2 changed files with 65 additions and 8 deletions
54
src/main.rs
54
src/main.rs
|
|
@ -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
19
templates/home.html
Normal 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>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue