Struct Oidc

Source
pub struct Oidc { /* private fields */ }
Available on crate feature experimental-oidc only.
Expand description

A high-level authentication API to interact with an OpenID Connect Provider.

Implementations§

Source§

impl Oidc

Source

pub async fn enable_cross_process_refresh_lock( &self, lock_value: String, ) -> Result<(), OidcError>

Enable a cross-process store lock on the state store, to coordinate refreshes across different processes.

Source

pub fn login_with_qr_code<'a>( &'a self, data: &'a QrCodeData, client_metadata: VerifiedClientMetadata, ) -> LoginWithQrCode<'a>

Available on crate feature e2e-encryption and non-WebAssembly only.

Log in using a QR code.

This method allows you to log in with a QR code, the existing device needs to display the QR code which this device can scan and call this method to log in.

A successful login using this method will automatically mark the device as verified and transfer all end-to-end encryption related secrets, like the private cross-signing keys and the backup key from the existing device to the new device.

§Example
use anyhow::bail;
use futures_util::StreamExt;
use matrix_sdk::{
    authentication::oidc::{
        types::registration::VerifiedClientMetadata,
        qrcode::{LoginProgress, QrCodeData, QrCodeModeData},
    },
    Client,
};
// You'll need to use a different library to scan and extract the raw bytes from the QR
// code.
let qr_code_data = QrCodeData::from_bytes(bytes)?;

// Fetch the homeserver out of the parsed QR code data.
let QrCodeModeData::Reciprocate{ server_name } = qr_code_data.mode_data else {
    bail!("The QR code is invalid, we did not receive a homeserver in the QR code.");
};

// Build the client as usual.
let client = Client::builder()
    .server_name_or_homeserver_url(server_name)
    .handle_refresh_tokens()
    .build()
    .await?;

let oidc = client.oidc();
let metadata: VerifiedClientMetadata = client_metadata();

// Subscribing to the progress is necessary since we need to input the check
// code on the existing device.
let login = oidc.login_with_qr_code(&qr_code_data, metadata);
let mut progress = login.subscribe_to_progress();

// Create a task which will show us the progress and tell us the check
// code to input in the existing device.
let task = tokio::spawn(async move {
    while let Some(state) = progress.next().await {
        match state {
            LoginProgress::Starting => (),
            LoginProgress::EstablishingSecureChannel { check_code } => {
                let code = check_code.to_digit();
                println!("Please enter the following code into the other device {code:02}");
            },
            LoginProgress::WaitingForToken { user_code } => {
                println!("Please use your other device to confirm the log in {user_code}")
            },
            LoginProgress::Done => break,
        }
    }
});

// Now run the future to complete the login.
login.await?;
task.abort();

println!("Successfully logged in: {:?} {:?}", client.user_id(), client.device_id());
Source

pub async fn url_for_oidc( &self, registrations: OidcRegistrations, redirect_uri: Url, prompt: Option<Prompt>, ) -> Result<OidcAuthorizationData, OidcError>

A higher level wrapper around the configuration and login methods that will take some client metadata, register the client if needed and begin the login process, returning the authorization data required to show a webview for a user to login to their account. Call Oidc::login_with_oidc_callback to finish the process when the webview is complete.

§Arguments
  • registrations - The storage where the registered client ID will be loaded from, if the client is already registered, or stored into, if the client is not registered yet.

  • redirect_uri - The URI where the end user will be redirected after authorizing the login. It must be one of the redirect URIs in the client metadata used for registration.

  • prompt - The desired user experience in the web UI. None means that the user wishes to login into an existing account, and Some(Prompt::Create) means that the user wishes to register a new account.

Source

pub async fn login_with_oidc_callback( &self, authorization_data: &OidcAuthorizationData, callback_url: Url, ) -> Result<()>

A higher level wrapper around the methods to complete a login after the user has logged in through a webview. This method should be used in tandem with Oidc::url_for_oidc.

Source

pub fn issuer(&self) -> Option<&str>

The OpenID Connect Provider used for authorization.

Returns None if the client was not registered or if the registration was not restored with Oidc::restore_registered_client() or Oidc::restore_session().

Source

pub async fn account_management_actions_supported( &self, ) -> Result<Option<Vec<AccountManagementAction>>, OidcError>

The account management actions supported by the provider’s account management URL.

Returns Ok(None) if the data was not found. Returns an error if the request to get the provider metadata fails.

Source

pub async fn fetch_account_management_url( &self, action: Option<AccountManagementActionFull>, ) -> Result<Option<Url>, OidcError>

Build the URL where the user can manage their account.

§Arguments

Returns Ok(None) if the URL was not found. Returns an error if the request to get the provider metadata fails or the URL could not be parsed.

Source

pub async fn account_management_url( &self, action: Option<AccountManagementActionFull>, ) -> Result<Option<Url>, OidcError>

Get the account management URL where the user can manage their identity-related settings.

§Arguments

Returns Ok(None) if the URL was not found. Returns an error if the request to get the provider metadata fails or the URL could not be parsed.

This method will cache the URL for a while, if the cache is not populated it will internally call Oidc::fetch_account_management_url() and cache the resulting URL before returning it.

Source

pub async fn provider_metadata( &self, ) -> Result<VerifiedProviderMetadata, OauthDiscoveryError>

Fetch the OAuth 2.0 server metadata of the homeserver.

Returns an error if a problem occurred when fetching or validating the metadata.

Source

pub fn client_id(&self) -> Option<&ClientId>

The OpenID Connect unique identifier of this client obtained after registration.

Returns None if the client was not registered or if the registration was not restored with Oidc::restore_registered_client() or Oidc::restore_session().

Source

pub fn user_session(&self) -> Option<UserSession>

The OpenID Connect user session of this client.

Returns None if the client was not logged in with the OpenID Connect API.

Source

pub fn full_session(&self) -> Option<OidcSession>

The full OpenID Connect session of this client.

Returns None if the client was not logged in with the OpenID Connect API.

Source

pub async fn register_client( &self, client_metadata: VerifiedClientMetadata, software_statement: Option<String>, ) -> Result<ClientRegistrationResponse, OidcError>

Register a client with the OAuth 2.0 server.

This should be called before any authorization request with an unknown authorization server. If the client is already registered with the given issuer, it should use Oidc::restore_registered_client().

Note that this method only supports public clients, i.e. clients with the token_endpoint_auth_method field in VerifiedClientMetadata set to none.

The client should adapt the security measures enabled in its metadata according to the capabilities advertised in Oidc::provider_metadata().

§Arguments
  • client_metadata - The VerifiedClientMetadata to register.

  • software_statement - A software statement, a digitally signed version of the metadata, as a JWT. Any claim in this JWT will override the corresponding field in the client metadata. It must include a software_id claim that is used to uniquely identify a client and ensure the same client_id is returned on subsequent registration, allowing to update the registered client metadata.

The client ID in the response should be persisted for future use and reused for the same authorization server, identified by the Oidc::issuer(), along with the client metadata sent to the provider, even for different sessions or user accounts.

§Panic

Panics if the authentication data was already set.

§Example
use matrix_sdk::{Client, ServerName};
use matrix_sdk::authentication::oidc::registrations::ClientId;
use matrix_sdk::authentication::oidc::types::registration::ClientMetadata;
let server_name = ServerName::parse("myhomeserver.org")?;
let client = Client::builder().server_name(&server_name).build().await?;
let oidc = client.oidc();

if let Err(error) = oidc.provider_metadata().await {
    if error.is_not_supported() {
        println!("OAuth 2.0 is not supported");
    }

    return Err(error.into());
}

let response = oidc
    .register_client(client_metadata.clone(), None)
    .await?;

println!(
    "Registered with client_id: {}",
    response.client_id
);

// The API only supports clients without secrets.
let client_id = ClientId::new(response.client_id);
let issuer = oidc.issuer().expect("issuer should be set after registration");

persist_client_registration(issuer, &client_metadata, &client_id);
Source

pub fn restore_registered_client(&self, issuer: String, client_id: ClientId)

Set the data of a client that is registered with an OpenID Connect Provider.

This should be called when logging in with a provider that is already known by the client.

Note that this method only supports public clients, i.e. clients with no credentials.

§Arguments
  • issuer - The authorization server that was used to register the client.

  • client_id - The unique identifier to authenticate the client with the provider, obtained after registration.

§Panic

Panics if authentication data was already set.

Source

pub async fn restore_session(&self, session: OidcSession) -> Result<()>

Restore a previously logged in session.

This can be used to restore the client to a logged in state, including loading the sync state and the encryption keys from the store, if one was set up.

§Arguments
  • session - The session to restore.
§Panic

Panics if authentication data was already set.

Source

pub fn login( &self, redirect_uri: Url, device_id: Option<OwnedDeviceId>, ) -> Result<OidcAuthCodeUrlBuilder, OidcError>

Login via OpenID Connect with the Authorization Code flow.

This should be called after Oidc::register_client() or Oidc::restore_registered_client().

If this is a brand new login, Oidc::finish_login() must be called after Oidc::finish_authorization(), to finish loading the user session.

§Arguments
  • redirect_uri - The URI where the end user will be redirected after authorizing the login. It must be one of the redirect URIs sent in the client metadata during registration.

  • device_id - The unique ID that will be associated with the session. If not set, a random one will be generated. It can be an existing device ID from a previous login call. Note that this should be done only if the client also holds the corresponding encryption keys.

§Errors

Returns an error if the device ID is not valid.

§Example
use matrix_sdk::{Client};
let oidc = client.oidc();

oidc.restore_registered_client(
    issuer_info,
    client_id,
);

let auth_data = oidc.login(redirect_uri, None)?.build().await?;

// Open auth_data.url and wait for response at the redirect URI.
// The full URL obtained is called here `redirected_to_uri`.

let auth_response = AuthorizationResponse::parse_uri(&redirected_to_uri)?;

let code = match auth_response {
    AuthorizationResponse::Success(code) => code,
    AuthorizationResponse::Error(error) => {
        return Err(anyhow!("Authorization failed: {:?}", error));
    }
};

let _tokens_response = oidc.finish_authorization(code).await?;

// Important! Without this we can't access the full session.
oidc.finish_login().await?;

// The session tokens can be persisted either from the response, or from
// the `Client::session_tokens()` method.

// You can now make any request compatible with the requested scope.
let _me = client.whoami().await?;
Source

pub async fn finish_login(&self) -> Result<()>

Finish the login process.

Must be called after Oidc::finish_authorization() after logging into a brand new session, to load the last part of the user session and complete the initialization of the Client.

§Panic

Panics if the login was already completed.

Source

pub async fn finish_authorization( &self, auth_code: AuthorizationCode, ) -> Result<(), OidcError>

Finish the authorization process.

This method should be called after the URL returned by OidcAuthCodeUrlBuilder::build() has been presented and the user has been redirected to the redirect URI after a successful authorization.

If the authorization has not been successful, Oidc::abort_authorization() should be used instead to clean up the local data.

§Arguments
  • auth_code - The response received as part of the redirect URI when the authorization was successful.

Returns an error if a request fails.

Source

pub async fn abort_authorization(&self, state: &CsrfToken)

Abort the authorization process.

This method should be called after the URL returned by OidcAuthCodeUrlBuilder::build() has been presented and the user has been redirected to the redirect URI after a failed authorization, or if the authorization should be aborted before it is completed.

If the authorization has been successful, Oidc::finish_authorization() should be used instead.

§Arguments
  • state - The state received as part of the redirect URI when the authorization failed, or the one provided in OidcAuthorizationData after building the authorization URL.
Source

pub async fn refresh_access_token(&self) -> Result<(), RefreshTokenError>

Refresh the access token.

This should be called when the access token has expired. It should not be needed to call this manually if the Client was constructed with ClientBuilder::handle_refresh_tokens().

This method is protected behind a lock, so calling this method several times at once will only call the endpoint once and all subsequent calls will wait for the result of the first call. The first call will return Ok(Some(response)) or a RefreshTokenError, while the others will return Ok(None) if the token was refreshed by the first call or the same RefreshTokenError, if it failed.

Source

pub async fn logout(&self) -> Result<(), OidcError>

Log out from the currently authenticated session.

Trait Implementations§

Source§

impl Clone for Oidc

Source§

fn clone(&self) -> Oidc

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Oidc

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Oidc

§

impl !RefUnwindSafe for Oidc

§

impl Send for Oidc

§

impl Sync for Oidc

§

impl Unpin for Oidc

§

impl !UnwindSafe for Oidc

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T> CompatExt for T

§

fn compat(self) -> Compat<T>

Applies the [Compat] adapter by value. Read more
§

fn compat_ref(&self) -> Compat<&T>

Applies the [Compat] adapter by shared reference. Read more
§

fn compat_mut(&mut self) -> Compat<&mut T>

Applies the [Compat] adapter by mutable reference. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T, UT> HandleAlloc<UT> for T
where T: Send + Sync,

Source§

fn new_handle(value: Arc<T>) -> Handle

Create a new handle for an Arc value Read more
Source§

fn clone_handle(handle: Handle) -> Handle

Clone a handle Read more
Source§

fn consume_handle(handle: Handle) -> Arc<T>

Consume a handle, getting back the initial Arc<>
Source§

fn get_arc(handle: Handle) -> Arc<Self>

Get a clone of the Arc<> using a “borrowed” handle. Read more
Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<T> Any for T
where T: Any,

Source§

impl<T> AsyncTraitDeps for T

Source§

impl<T> CloneAny for T
where T: Any + Clone,

Source§

impl<T> CloneAnySend for T
where T: Any + Send + Clone,

Source§

impl<T> CloneAnySendSync for T
where T: Any + Send + Sync + Clone,

Source§

impl<T> CloneAnySync for T
where T: Any + Sync + Clone,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T

Source§

impl<T> SendOutsideWasm for T
where T: Send,

Source§

impl<T> SyncOutsideWasm for T
where T: Sync,