diff --git a/crates/ruma-client-api/src/uiaa.rs b/crates/ruma-client-api/src/uiaa.rs index 603d6080b9..0e8be6fefe 100644 --- a/crates/ruma-client-api/src/uiaa.rs +++ b/crates/ruma-client-api/src/uiaa.rs @@ -61,6 +61,12 @@ pub enum AuthData { /// This type is only valid during account registration. Terms(Terms), + /// OAuth 2.0 (`m.oauth`). + /// + /// This type is only valid with the cross-signing keys upload endpoint, after logging in with + /// the OAuth 2.0 API. + OAuth(OAuth), + #[doc(hidden)] _Custom(CustomAuthData), } @@ -100,6 +106,9 @@ impl AuthData { "m.registration_token" => Self::RegistrationToken(deserialize_variant(session, data)?), "org.matrix.login.jwt" => Self::Jwt(deserialize_variant(session, data)?), "m.login.terms" => Self::Terms(deserialize_variant(session, data)?), + "m.oauth" | "org.matrix.cross_signing_reset" => { + Self::OAuth(deserialize_variant(session, data)?) + } _ => { Self::_Custom(CustomAuthData { auth_type: auth_type.into(), session, extra: data }) } @@ -123,6 +132,7 @@ impl AuthData { Self::FallbackAcknowledgement(_) => None, Self::Jwt(_) => Some(AuthType::Jwt), Self::Terms(_) => Some(AuthType::Terms), + Self::OAuth(_) => Some(AuthType::OAuth), Self::_Custom(c) => Some(AuthType::_Custom(PrivOwnedStr(c.auth_type.as_str().into()))), } } @@ -139,6 +149,7 @@ impl AuthData { Self::FallbackAcknowledgement(x) => Some(&x.session), Self::Jwt(x) => x.session.as_deref(), Self::Terms(x) => x.session.as_deref(), + Self::OAuth(x) => x.session.as_deref(), Self::_Custom(x) => x.session.as_deref(), } } @@ -180,8 +191,8 @@ impl AuthData { Cow::Owned(serialize(RegistrationToken { token: x.token.clone(), session: None })) } Self::Jwt(x) => Cow::Owned(serialize(Jwt { token: x.token.clone(), session: None })), - // Dummy, fallback acknowledgement, and terms of service have no associated data - Self::Dummy(_) | Self::FallbackAcknowledgement(_) | Self::Terms(_) => { + // Dummy, fallback acknowledgement, terms of service, and OAuth have no associated data + Self::Dummy(_) | Self::FallbackAcknowledgement(_) | Self::Terms(_) | Self::OAuth(_) => { Cow::Owned(JsonObject::default()) } Self::_Custom(c) => Cow::Borrowed(&c.extra), @@ -202,6 +213,7 @@ impl fmt::Debug for AuthData { Self::Jwt(inner) => inner.fmt(f), Self::FallbackAcknowledgement(inner) => inner.fmt(f), Self::Terms(inner) => inner.fmt(f), + Self::OAuth(inner) => inner.fmt(f), Self::_Custom(inner) => inner.fmt(f), } } @@ -235,6 +247,9 @@ impl<'de> Deserialize<'de> for AuthData { } Some("org.matrix.login.jwt") => from_raw_json_value(&json).map(Self::Jwt), Some("m.login.terms") => from_raw_json_value(&json).map(Self::Terms), + Some("m.oauth" | "org.matrix.cross_signing_reset") => { + from_raw_json_value(&json).map(Self::OAuth) + } None => from_raw_json_value(&json).map(Self::FallbackAcknowledgement), Some(_) => from_raw_json_value(&json).map(Self::_Custom), } @@ -284,6 +299,13 @@ pub enum AuthType { #[ruma_enum(rename = "m.login.terms")] Terms, + /// OAuth 2.0 (`m.oauth`). + /// + /// This type is only valid with the cross-signing keys upload endpoint, after logging in with + /// the OAuth 2.0 API. + #[ruma_enum(rename = "m.oauth", alias = "org.matrix.cross_signing_reset")] + OAuth, + #[doc(hidden)] _Custom(PrivOwnedStr), } @@ -506,6 +528,24 @@ impl Terms { } } +/// Data for an [OAuth 2.0-based] UIAA flow. +/// +/// [OAuth 2.0-based]: https://spec.matrix.org/latest/client-server-api/#oauth-authentication +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)] +#[serde(tag = "type", rename = "m.oauth")] +pub struct OAuth { + /// The value of the session key given by the homeserver, if any. + pub session: Option, +} + +impl OAuth { + /// Construct an empty `OAuth`. + pub fn new() -> Self { + Self::default() + } +} + #[doc(hidden)] #[derive(Clone, Deserialize, Serialize)] #[non_exhaustive] @@ -708,6 +748,26 @@ impl AuthFlow { } } +/// Parameters for an [OAuth 2.0-based] UIAA flow. +/// +/// [OAuth 2.0-based]: https://spec.matrix.org/latest/client-server-api/#oauth-authentication +#[derive(Clone, Debug, Deserialize, Serialize)] +#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)] +pub struct OAuthParams { + /// A URL pointing to the homeserver's OAuth 2.0 account management web UI where the user can + /// approve the action. + /// + /// Must be a valid URI with scheme `http://` or `https://`, the latter being recommended. + pub url: String, +} + +impl OAuthParams { + /// Construct an `OAuthParams` with the given URL. + pub fn new(url: String) -> Self { + Self { url } + } +} + /// Contains either a User-Interactive Authentication API response body or a Matrix error. #[derive(Clone, Debug)] #[allow(clippy::exhaustive_enums)]