1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Add client-side support for RP-Initiated logout

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille
2023-08-05 12:00:53 +02:00
committed by Quentin Gliech
parent 4cdb24ffe4
commit ba7d17f25c
7 changed files with 223 additions and 2 deletions

View File

@ -16,7 +16,7 @@
//!
//! [OpenID Connect]: https://openid.net/connect/
use std::{ops::Deref, str::FromStr};
use std::{fmt, ops::Deref, str::FromStr};
use language_tags::LanguageTag;
use mas_iana::{
@ -25,7 +25,10 @@ use mas_iana::{
};
use parse_display::{Display, FromStr, ParseError};
use serde::{Deserialize, Serialize};
use serde_with::{skip_serializing_none, DeserializeFromStr, SerializeDisplay};
use serde_with::{
formats::SpaceSeparator, serde_as, skip_serializing_none, DeserializeFromStr, SerializeDisplay,
StringWithSeparator,
};
use thiserror::Error;
use url::Url;
@ -471,6 +474,11 @@ pub struct ProviderMetadata {
///
/// [device authorization endpoint]: https://www.rfc-editor.org/rfc/rfc8628
pub device_authorization_endpoint: Option<Url>,
/// URL of the authorization server's [RP-Initiated Logout endpoint].
///
/// [RP-Initiated Logout endpoint]: https://openid.net/specs/openid-connect-rpinitiated-1_0.html
pub end_session_endpoint: Option<Url>,
}
impl ProviderMetadata {
@ -593,6 +601,10 @@ impl ProviderMetadata {
)?;
}
if let Some(url) = &metadata.end_session_endpoint {
validate_url("end_session_endpoint", url, ExtraUrlRestrictions::None)?;
}
Ok(metadata)
}
@ -1057,6 +1069,66 @@ fn validate_signing_alg_values_supported<'a>(
Ok(())
}
/// The body of a request to the [RP-Initiated Logout Endpoint].
///
/// [RP-Initiated Logout Endpoint]: https://openid.net/specs/openid-connect-rpinitiated-1_0.html
#[skip_serializing_none]
#[serde_as]
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct RpInitiatedLogoutRequest {
/// ID Token previously issued by the OP to the RP.
///
/// Recommended, used as a hint about the End-User's current authenticated
/// session with the Client.
pub id_token_hint: Option<String>,
/// Hint to the Authorization Server about the End-User that is logging out.
///
/// The value and meaning of this parameter is left up to the OP's
/// discretion. For instance, the value might contain an email address,
/// phone number, username, or session identifier pertaining to the RP's
/// session with the OP for the End-User.
pub logout_hint: Option<String>,
/// OAuth 2.0 Client Identifier valid at the Authorization Server.
///
/// The most common use case for this parameter is to specify the Client
/// Identifier when `post_logout_redirect_uri` is used but `id_token_hint`
/// is not. Another use is for symmetrically encrypted ID Tokens used as
/// `id_token_hint` values that require the Client Identifier to be
/// specified by other means, so that the ID Tokens can be decrypted by
/// the OP.
pub client_id: Option<String>,
/// URI to which the RP is requesting that the End-User's User Agent be
/// redirected after a logout has been performed.
///
/// The value MUST have been previously registered with the OP, using the
/// `post_logout_redirect_uris` registration parameter.
pub post_logout_redirect_uri: Option<Url>,
/// Opaque value used by the RP to maintain state between the logout request
/// and the callback to the endpoint specified by the
/// `post_logout_redirect_uri` parameter.
pub state: Option<String>,
/// End-User's preferred languages and scripts for the user interface,
/// ordered by preference.
#[serde_as(as = "Option<StringWithSeparator::<SpaceSeparator, LanguageTag>>")]
#[serde(default)]
pub ui_locales: Option<Vec<LanguageTag>>,
}
impl fmt::Debug for RpInitiatedLogoutRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RpInitiatedLogoutRequest")
.field("logout_hint", &self.logout_hint)
.field("post_logout_redirect_uri", &self.post_logout_redirect_uri)
.field("ui_locales", &self.ui_locales)
.finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests {
use assert_matches::assert_matches;

View File

@ -124,6 +124,7 @@ pub struct ClientMetadataSerdeHelper {
introspection_signed_response_alg: Option<JsonWebSignatureAlg>,
introspection_encrypted_response_alg: Option<JsonWebEncryptionAlg>,
introspection_encrypted_response_enc: Option<JsonWebEncryptionEnc>,
post_logout_redirect_uris: Option<Vec<Url>>,
#[serde(flatten)]
extra: ClientMetadataLocalizedFields,
}
@ -168,6 +169,7 @@ impl From<VerifiedClientMetadata> for ClientMetadataSerdeHelper {
introspection_signed_response_alg,
introspection_encrypted_response_alg,
introspection_encrypted_response_enc,
post_logout_redirect_uris,
},
} = metadata;
@ -202,6 +204,7 @@ impl From<VerifiedClientMetadata> for ClientMetadataSerdeHelper {
introspection_signed_response_alg,
introspection_encrypted_response_alg,
introspection_encrypted_response_enc,
post_logout_redirect_uris,
extra: ClientMetadataLocalizedFields {
client_name,
logo_uri,
@ -246,6 +249,7 @@ impl From<ClientMetadataSerdeHelper> for ClientMetadata {
introspection_signed_response_alg,
introspection_encrypted_response_alg,
introspection_encrypted_response_enc,
post_logout_redirect_uris,
extra:
ClientMetadataLocalizedFields {
client_name,
@ -292,6 +296,7 @@ impl From<ClientMetadataSerdeHelper> for ClientMetadata {
introspection_signed_response_alg,
introspection_encrypted_response_alg,
introspection_encrypted_response_enc,
post_logout_redirect_uris,
}
}
}

View File

@ -418,6 +418,12 @@ pub struct ClientMetadata {
/// [JWE]: http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption
/// [introspection endpoint]: https://www.rfc-editor.org/info/rfc7662
pub introspection_encrypted_response_enc: Option<JsonWebEncryptionEnc>,
/// `post_logout_redirect_uri` values that are pre-registered by the client
/// for use at the provider's [RP-Initiated Logout endpoint].
///
/// [RP-Initiated Logout endpoint]: https://openid.net/specs/openid-connect-rpinitiated-1_0.html
pub post_logout_redirect_uris: Option<Vec<Url>>,
}
impl ClientMetadata {