mirror of
https://codeberg.org/pfzetto/axum-oidc
synced 2025-12-09 22:55:17 +01:00
Added first implementation of RP Initiated Logout
Created a new extractor for RP-Initiated-Logout and modified example to use it.
This commit is contained in:
parent
a522b7936d
commit
1844b880c1
8 changed files with 171 additions and 17 deletions
|
|
@ -1,9 +1,13 @@
|
|||
use std::ops::Deref;
|
||||
use std::{borrow::Cow, ops::Deref};
|
||||
|
||||
use crate::{error::ExtractorError, AdditionalClaims};
|
||||
use async_trait::async_trait;
|
||||
use axum_core::extract::FromRequestParts;
|
||||
use http::request::Parts;
|
||||
use axum::response::Redirect;
|
||||
use axum_core::{
|
||||
extract::FromRequestParts,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use http::{request::Parts, uri::PathAndQuery, Uri};
|
||||
use openidconnect::{core::CoreGenderClaim, IdTokenClaims};
|
||||
|
||||
/// Extractor for the OpenID Connect Claims.
|
||||
|
|
@ -81,3 +85,80 @@ impl AsRef<str> for OidcAccessToken {
|
|||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OidcRpInitiatedLogout {
|
||||
pub(crate) end_session_endpoint: Uri,
|
||||
pub(crate) id_token_hint: String,
|
||||
pub(crate) client_id: String,
|
||||
pub(crate) post_logout_redirect_uri: Option<Uri>,
|
||||
pub(crate) state: Option<String>,
|
||||
}
|
||||
|
||||
impl OidcRpInitiatedLogout {
|
||||
pub fn with_post_logout_redirect(mut self, uri: Uri) -> Self {
|
||||
self.post_logout_redirect_uri = Some(uri);
|
||||
self
|
||||
}
|
||||
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();
|
||||
|
||||
let query = {
|
||||
let mut query = Vec::with_capacity(4);
|
||||
query.push(("id_token_hint", Cow::Borrowed(&self.id_token_hint)));
|
||||
query.push(("client_id", Cow::Borrowed(&self.client_id)));
|
||||
|
||||
if let Some(post_logout_redirect_uri) = &self.post_logout_redirect_uri {
|
||||
query.push((
|
||||
"post_logout_redirect_uri",
|
||||
Cow::Owned(post_logout_redirect_uri.to_string()),
|
||||
));
|
||||
}
|
||||
if let Some(state) = &self.state {
|
||||
query.push(("state", Cow::Borrowed(state)));
|
||||
}
|
||||
|
||||
query
|
||||
.into_iter()
|
||||
.map(|(k, v)| format!("{}={}", k, urlencoding::encode(v.as_str())))
|
||||
.collect::<Vec<_>>()
|
||||
.join("&")
|
||||
};
|
||||
|
||||
let path_and_query = match parts.path_and_query {
|
||||
Some(path_and_query) => {
|
||||
PathAndQuery::from_maybe_shared(format!("{}?{}", path_and_query.path(), query))
|
||||
}
|
||||
None => PathAndQuery::from_maybe_shared(format!("?{}", query)),
|
||||
};
|
||||
parts.path_and_query = Some(path_and_query.unwrap());
|
||||
|
||||
Uri::from_parts(parts).unwrap()
|
||||
}
|
||||
}
|
||||
#[async_trait]
|
||||
impl<S> FromRequestParts<S> for OidcRpInitiatedLogout
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = ExtractorError;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
|
||||
parts
|
||||
.extensions
|
||||
.get::<Self>()
|
||||
.cloned()
|
||||
.ok_or(ExtractorError::Unauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl IntoResponse for OidcRpInitiatedLogout {
|
||||
fn into_response(self) -> Response {
|
||||
Redirect::temporary(&self.uri().to_string()).into_response()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue