Cleanup of RP-Initiated Logout

Added comments
Removed unwraps
Reworked Session container and middlewares
This commit is contained in:
Paul Zinselmeyer 2024-03-26 21:06:50 +01:00
parent 1844b880c1
commit 6528a6f247
Signed by: pfzetto
GPG key ID: B471A1AF06C895FD
5 changed files with 175 additions and 159 deletions

View file

@ -2,11 +2,7 @@ use std::{borrow::Cow, ops::Deref};
use crate::{error::ExtractorError, AdditionalClaims};
use async_trait::async_trait;
use axum::response::Redirect;
use axum_core::{
extract::FromRequestParts,
response::{IntoResponse, Response},
};
use axum_core::extract::FromRequestParts;
use http::{request::Parts, uri::PathAndQuery, Uri};
use openidconnect::{core::CoreGenderClaim, IdTokenClaims};
@ -82,10 +78,13 @@ impl Deref for OidcAccessToken {
impl AsRef<str> for OidcAccessToken {
fn as_ref(&self) -> &str {
self.0.as_str()
&self.0
}
}
/// Extractor for the [OpenID Connect RP-Initialized Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) URL
///
/// This Extractor will only succed when the cached session is valid, [crate::middleware::OidcAuthMiddleware] is loaded and the issuer supports RP-Initialized Logout.
#[derive(Clone)]
pub struct OidcRpInitiatedLogout {
pub(crate) end_session_endpoint: Uri,
@ -96,19 +95,23 @@ pub struct OidcRpInitiatedLogout {
}
impl OidcRpInitiatedLogout {
/// set uri that the user is redirected to after logout.
/// This uri must be in the allowed by issuer.
pub fn with_post_logout_redirect(mut self, uri: Uri) -> Self {
self.post_logout_redirect_uri = Some(uri);
self
}
/// set the state parameter that is appended as a query to the post logout redirect uri.
pub fn with_state(mut self, state: String) -> Self {
self.state = Some(state);
self
}
pub fn uri(self) -> Uri {
let mut parts = self.end_session_endpoint.into_parts();
/// get the uri that the client needs to access for logout
pub fn uri(&self) -> Result<Uri, http::Error> {
let mut parts = self.end_session_endpoint.clone().into_parts();
let query = {
let mut query = Vec::with_capacity(4);
let mut query: Vec<(&str, Cow<'_, str>)> = Vec::with_capacity(4);
query.push(("id_token_hint", Cow::Borrowed(&self.id_token_hint)));
query.push(("client_id", Cow::Borrowed(&self.client_id)));
@ -124,7 +127,7 @@ impl OidcRpInitiatedLogout {
query
.into_iter()
.map(|(k, v)| format!("{}={}", k, urlencoding::encode(v.as_str())))
.map(|(k, v)| format!("{}={}", k, urlencoding::encode(&v)))
.collect::<Vec<_>>()
.join("&")
};
@ -135,11 +138,12 @@ impl OidcRpInitiatedLogout {
}
None => PathAndQuery::from_maybe_shared(format!("?{}", query)),
};
parts.path_and_query = Some(path_and_query.unwrap());
parts.path_and_query = Some(path_and_query?);
Uri::from_parts(parts).unwrap()
Ok(Uri::from_parts(parts)?)
}
}
#[async_trait]
impl<S> FromRequestParts<S> for OidcRpInitiatedLogout
where
@ -155,10 +159,3 @@ where
.ok_or(ExtractorError::Unauthorized)
}
}
#[async_trait]
impl IntoResponse for OidcRpInitiatedLogout {
fn into_response(self) -> Response {
Redirect::temporary(&self.uri().to_string()).into_response()
}
}