From 29f6606d9901d00c85ae4e5e0abe2fba1d59ae6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Fri, 21 Mar 2025 19:57:12 +0100 Subject: [PATCH] refactor(examples): Rename oidc_cli to oauth_cli MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And update the docs. Signed-off-by: Kévin Commaille --- Cargo.lock | 2 +- .../src/authentication/oauth/mod.rs | 4 +- examples/{oidc_cli => oauth_cli}/Cargo.toml | 4 +- examples/{oidc_cli => oauth_cli}/src/main.rs | 93 +++++++------------ 4 files changed, 37 insertions(+), 66 deletions(-) rename examples/{oidc_cli => oauth_cli}/Cargo.toml (92%) rename examples/{oidc_cli => oauth_cli}/src/main.rs (89%) diff --git a/Cargo.lock b/Cargo.lock index 20d5411b7..43e5c1cc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1542,7 +1542,7 @@ dependencies = [ ] [[package]] -name = "example-oidc-cli" +name = "example-oauth-cli" version = "0.1.0" dependencies = [ "anyhow", diff --git a/crates/matrix-sdk/src/authentication/oauth/mod.rs b/crates/matrix-sdk/src/authentication/oauth/mod.rs index a30062af7..c9f743c2c 100644 --- a/crates/matrix-sdk/src/authentication/oauth/mod.rs +++ b/crates/matrix-sdk/src/authentication/oauth/mod.rs @@ -120,14 +120,14 @@ //! # Examples //! //! Most methods have examples, there is also an example CLI application that -//! supports all the actions described here, in [`examples/oidc_cli`]. +//! supports all the actions described here, in [`examples/oauth_cli`]. //! //! [MSC3861]: https://github.com/matrix-org/matrix-spec-proposals/pull/3861 //! [areweoidcyet.com]: https://areweoidcyet.com/ //! [`ClientBuilder::handle_refresh_tokens()`]: crate::ClientBuilder::handle_refresh_tokens() //! [`Error`]: ruma::api::client::error::Error //! [`ErrorKind::UnknownToken`]: ruma::api::client::error::ErrorKind::UnknownToken -//! [`examples/oidc_cli`]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/examples/oidc_cli +//! [`examples/oauth_cli`]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/examples/oauth_cli use std::{ borrow::Cow, diff --git a/examples/oidc_cli/Cargo.toml b/examples/oauth_cli/Cargo.toml similarity index 92% rename from examples/oidc_cli/Cargo.toml rename to examples/oauth_cli/Cargo.toml index 8380da1ab..8bd2fe008 100644 --- a/examples/oidc_cli/Cargo.toml +++ b/examples/oauth_cli/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "example-oidc-cli" +name = "example-oauth-cli" version = "0.1.0" edition = "2021" publish = false license = "Apache-2.0" [[bin]] -name = "example-oidc-cli" +name = "example-oauth-cli" test = false [dependencies] diff --git a/examples/oidc_cli/src/main.rs b/examples/oauth_cli/src/main.rs similarity index 89% rename from examples/oidc_cli/src/main.rs rename to examples/oauth_cli/src/main.rs index 3ad84a36a..cad80545c 100644 --- a/examples/oidc_cli/src/main.rs +++ b/examples/oauth_cli/src/main.rs @@ -44,13 +44,13 @@ use tokio::{fs, io::AsyncBufReadExt as _}; use url::Url; /// A command-line tool to demonstrate the steps requiring an interaction with -/// an OpenID Connect provider for a Matrix client, using the Authorization Code -/// flow. +/// an OAuth 2.0 authorization server for a Matrix client, using the +/// Authorization Code flow. /// /// You can test this against one of the servers from the OIDC playground: /// . /// -/// To use this, just run `cargo run -p example-oidc-cli`, and everything +/// To use this, just run `cargo run -p example-oauth-cli`, and everything /// is interactive after that. You might want to set the `RUST_LOG` environment /// variable to `warn` to reduce the noise in the logs. The program exits /// whenever an unexpected error occurs. @@ -64,14 +64,14 @@ async fn main() -> anyhow::Result<()> { // The folder containing this example's data. let data_dir = - dirs::data_dir().expect("no data_dir directory found").join("matrix_sdk/oidc_cli"); + dirs::data_dir().expect("no data_dir directory found").join("matrix_sdk/oauth_cli"); // The file where the session is persisted. let session_file = data_dir.join("session.json"); let cli = if session_file.exists() { - OidcCli::from_stored_session(session_file).await? + OAuthCli::from_stored_session(session_file).await? } else { - OidcCli::new(&data_dir, session_file).await? + OAuthCli::new(&data_dir, session_file).await? }; cli.run().await @@ -104,29 +104,22 @@ struct ClientSession { passphrase: String, } -/// The data needed to restore an OpenID Connect session. -#[derive(Debug, Serialize, Deserialize)] -struct Credentials { - /// The client ID obtained after registration. - client_id: ClientId, -} - /// The full session to persist. #[derive(Debug, Serialize, Deserialize)] struct StoredSession { /// The data to re-build the client. client_session: ClientSession, - /// The OIDC user session. + /// The OAuth 2.0 user session. user_session: UserSession, - /// The OIDC client credentials. - client_credentials: Credentials, + /// The OAuth 2.0 client ID. + client_id: ClientId, } -/// An OpenID Connect CLI. +/// An OAuth 2.0 CLI. #[derive(Clone, Debug)] -struct OidcCli { +struct OAuthCli { /// The Matrix client. client: Client, @@ -137,7 +130,7 @@ struct OidcCli { session_file: PathBuf, } -impl OidcCli { +impl OAuthCli { /// Create a new session by logging in. async fn new(data_dir: &Path, session_file: PathBuf) -> anyhow::Result { println!("No previous session found, logging in…"); @@ -151,22 +144,11 @@ impl OidcCli { // Persist the session to reuse it later. // This is not very secure, for simplicity. If the system provides a way of // storing secrets securely, it should be used instead. - // Note that we could also build the user session from the login response. let user_session = cli.client.oauth().user_session().expect("A logged-in client should have a session"); - // The client registration data should be persisted separately than the user - // session, to be reused for other sessions or user accounts with the same - // issuer. - // Also, client metadata should be persisted as it might change depending on - // the provider metadata. - let client_credentials = Credentials { client_id }; - - let serialized_session = serde_json::to_string(&StoredSession { - client_session, - user_session, - client_credentials, - })?; + let serialized_session = + serde_json::to_string(&StoredSession { client_session, user_session, client_id })?; fs::write(&cli.session_file, serialized_session).await?; println!("Session persisted in {}", cli.session_file.to_string_lossy()); @@ -176,9 +158,9 @@ impl OidcCli { Ok(cli) } - /// Register the OIDC client with the provider. + /// Register the OAuth 2.0 client with the authorization server. /// - /// Returns the ID of the client returned by the provider. + /// Returns the ID of the client returned by the server. async fn register_client(&self) -> anyhow::Result { let oauth = self.client.oauth(); @@ -193,21 +175,14 @@ impl OidcCli { ); } - let metadata = client_metadata(); - - // During registration, we have the option of providing a software statement, - // which is a digitally signed version of the client metadata. That would allow - // to update the metadata later without changing the client ID, but requires to - // have a way to serve public keys online to validate the signature of - // the JWT. - let res = oauth.register_client(&metadata).await?; + let res = oauth.register_client(&client_metadata()).await?; println!("\nRegistered successfully"); Ok(res.client_id) } - /// Login via the OIDC Authorization Code flow. + /// Login via the OAuth 2.0 Authorization Code flow. async fn login(&self) -> anyhow::Result<()> { let oauth = self.client.oauth(); @@ -247,7 +222,7 @@ impl OidcCli { // The session was serialized as JSON in a file. let serialized_session = fs::read_to_string(&session_file).await?; - let StoredSession { client_session, user_session, client_credentials } = + let StoredSession { client_session, user_session, client_id } = serde_json::from_str(&serialized_session)?; // Build the client with the previous settings from the session. @@ -260,7 +235,7 @@ impl OidcCli { println!("Restoring session for {}…", user_session.meta.user_id); - let session = OAuthSession { client_id: client_credentials.client_id, user: user_session }; + let session = OAuthSession { client_id, user: user_session }; // Restore the Matrix user session. client.restore_session(session).await?; @@ -370,7 +345,9 @@ impl OidcCli { if let Some(handle) = encryption.reset_cross_signing().await? { match handle.auth_type() { CrossSigningResetAuthType::Uiaa(_) => { - unimplemented!("This should never happen, this is after all the OIDC example.") + unimplemented!( + "This should never happen, this is after all the OAuth 2.0 example." + ) } CrossSigningResetAuthType::OAuth(o) => { println!( @@ -396,12 +373,12 @@ impl OidcCli { let user_id = client.user_id().expect("A logged in client has a user ID"); let device_id = client.device_id().expect("A logged in client has a device ID"); let homeserver = client.homeserver(); - let issuer = oauth.issuer().expect("A logged in OIDC client has an issuer"); + let issuer = oauth.issuer().expect("A logged in OAuth 2.0 client has an issuer"); println!("\nUser ID: {user_id}"); println!("Device ID: {device_id}"); println!("Homeserver URL: {homeserver}"); - println!("OpenID Connect provider: {issuer}"); + println!("OAuth 2.0 authorization server: {issuer}"); } /// Get the account management URL. @@ -598,8 +575,7 @@ impl OidcCli { /// Build a new client. /// -/// Returns the client, the data required to restore the client, and the OIDC -/// issuer advertised by the homeserver. +/// Returns the client and the data required to restore the client. async fn build_client(data_dir: &Path) -> anyhow::Result<(Client, ClientSession)> { let db_path = data_dir.join("db"); @@ -679,12 +655,7 @@ async fn build_client(data_dir: &Path) -> anyhow::Result<(Client, ClientSession) } } -/// Generate the OIDC client metadata. -/// -/// For simplicity, we use most of the default values here, but usually this -/// should be adapted to the provider metadata to make interactions as secure as -/// possible, for example by using the most secure signing algorithms supported -/// by the provider. +/// Generate the OAuth 2.0 client metadata. fn client_metadata() -> Raw { // Native clients should be able to register the IPv4 and IPv6 loopback // interfaces and then point to any port when needing a redirect URI. An @@ -700,11 +671,11 @@ fn client_metadata() -> Raw { ); let metadata = ClientMetadata { - // The following fields should be displayed in the OIDC provider interface as part of the - // process to get the user's consent. It means that these should contain real data so the - // user can make sure that they allow the proper application. - // We are cheating here because this is an example. - client_name: Some(Localized::new("matrix-rust-sdk-oidc-cli".to_owned(), [])), + // The following fields should be displayed in the OAuth 2.0 authorization server's + // web UI as part of the process to get the user's consent. It means that these + // should contain real data so the user can make sure that they allow the proper + // application. We are cheating here because this is an example. + client_name: Some(Localized::new("matrix-rust-sdk-oauth-cli".to_owned(), [])), policy_uri: Some(client_uri.clone()), tos_uri: Some(client_uri.clone()), ..ClientMetadata::new(