diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-17 21:38:39 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-17 21:38:39 +0100 |
commit | 49b615210cd1699daaf231508d59915c068dc7f8 (patch) | |
tree | f1a60b709a46047ef7616dba1fa02f7b1d31b592 | |
parent | 455139ba2c73220da9e930838e876c59af6011f4 (diff) | |
download | gnix-49b615210cd1699daaf231508d59915c068dc7f8.tar gnix-49b615210cd1699daaf231508d59915c068dc7f8.tar.bz2 gnix-49b615210cd1699daaf231508d59915c068dc7f8.tar.zst |
gnix-auth-no-redirect
-rw-r--r-- | readme.md | 5 | ||||
-rw-r--r-- | src/modules/auth/cookie.rs | 47 |
2 files changed, 32 insertions, 20 deletions
@@ -167,8 +167,9 @@ themselves; in that case the request is passed on. gnix and can therefore be used by applications. Alternatively a login may be implemented by returning the `gnix-auth-success` header with a username as the value from the `fail` handler, which is handled like a sucessful login - for that user. This method can be useful for implementing custom login logic - like OTP login or a CAPTCHA. + for that user. If `gnix-auth-no-redirect` is set the response of the `fail` + handler is passed instead of a redirect being sent. This method can be + useful for implementing custom login logic like OTP login or a CAPTCHA. - `users`: list of valid logins (credentials) - `expire`: seconds before logins expire; not setting this option keeps the login valid forever on the server but cleared after the session on the diff --git a/src/modules/auth/cookie.rs b/src/modules/auth/cookie.rs index 091d41e..e078b6f 100644 --- a/src/modules/auth/cookie.rs +++ b/src/modules/auth/cookie.rs @@ -77,9 +77,7 @@ impl Node for CookieAuth { debug!("login attempt for {username:?}"); if self.users.authentificate(username, password) { debug!("login success via creds"); - Ok(apply_login_success_headers( - context, &self, referrer, username, - )) + Ok(login_success_response(context, &self, referrer, username)) } else { debug!("login fail"); let mut r = Response::new(BoxBody::<_, ServiceError>::new( @@ -134,12 +132,17 @@ impl Node for CookieAuth { let mut r = self.fail.handle(context, request).await?; if let Some(username) = r.headers_mut().remove("gnix-auth-success") { debug!("login success via fail handler"); - Ok(apply_login_success_headers( - context, - &self, - referrer, - username.to_str()?, - )) + if r.headers_mut().remove("gnix-auth-no-redirect").is_some() { + apply_login_success_headers(context, &self, username.to_str()?, &mut r); + Ok(r) + } else { + Ok(login_success_response( + context, + &self, + referrer, + username.to_str()?, + )) + } } else { debug!("unauthorized"); *r.status_mut() = StatusCode::UNAUTHORIZED; @@ -153,9 +156,9 @@ impl Node for CookieAuth { fn apply_login_success_headers( context: &mut NodeContext, node: &CookieAuth, - referrer: Option<HeaderValue>, username: &str, -) -> Response<BoxBody<Bytes, ServiceError>> { + r: &mut Response<BoxBody<Bytes, ServiceError>>, +) { let nonce = [(); 12].map(|_| random::<u8>()); let plaintext = unix_seconds().to_be_bytes(); let mut ciphertext = context @@ -169,7 +172,6 @@ fn apply_login_success_headers( }, ) .unwrap(); - ciphertext.extend(nonce); let auth = base64::engine::general_purpose::URL_SAFE.encode(ciphertext); @@ -181,12 +183,6 @@ fn apply_login_success_headers( write!(cookie_opts, "; Secure").unwrap(); } - let mut r = Response::new(BoxBody::<_, ServiceError>::new( - String::new().clone().map_err(|_| unreachable!()), - )); - *r.status_mut() = StatusCode::FOUND; - r.headers_mut() - .append(LOCATION, referrer.unwrap_or(HeaderValue::from_static("/"))); r.headers_mut().append( SET_COOKIE, HeaderValue::from_str(&format!( @@ -200,6 +196,21 @@ fn apply_login_success_headers( SET_COOKIE, HeaderValue::from_str(&format!("gnix_auth={}{}", auth, cookie_opts)).unwrap(), ); +} + +fn login_success_response( + context: &mut NodeContext, + node: &CookieAuth, + referrer: Option<HeaderValue>, + username: &str, +) -> Response<BoxBody<Bytes, ServiceError>> { + let mut r = Response::new(BoxBody::<_, ServiceError>::new( + String::new().clone().map_err(|_| unreachable!()), + )); + *r.status_mut() = StatusCode::FOUND; + r.headers_mut() + .append(LOCATION, referrer.unwrap_or(HeaderValue::from_static("/"))); + apply_login_success_headers(context, node, username, &mut r); r } |