Skip to content

Conversation

@zecakeh
Copy link
Collaborator

@zecakeh zecakeh commented Sep 8, 2022

This is a WIP implementation of OpenID Connect authentication using matrix-org/matrix-authentication-service#347.

I tried to write a thorough documentation in the oidc module on how to use it/what it supports.

This has been successfully tested against the synapse-oidc.lab.element.dev server from the OIDC Playground using the example CLI in examples/oidc-cli (logging and syncing). There is one quirk though, automatic refresh of token doesn't work because we don't seem to get the proper error type from Synapse.

It is currently not compatible with the synapse-auth0-oidc.lab.element.dev because of a metadata deserialization issue, and hasn't been tested with the 2 others because they don't have open registration according to the table.

Related to #859

@zecakeh zecakeh marked this pull request as draft September 8, 2022 18:06
@zecakeh
Copy link
Collaborator Author

zecakeh commented Sep 8, 2022

@pixlwave I haven't worked on the FFI bindings, will you handle that yourself?

@pixlwave
Copy link
Member

@zecakeh Yep, that’s totally fine by me, I’ll open another PR for the bindings when this gets merged 👍

Thanks for doing all the legwork on this 🙌

Copy link
Member

@sandhose sandhose left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a bunch of comments, but it looks good overall

A few things that I feel like I'm missing:

  • how does the refresh token logic work? Can we make it transparent for the user?
  • how transparent is it for an SDK user that it is an OIDC session?
  • why is there both a builder-pattern struct to build an authorization request and one as a function with a bunch of parameters?

//! [`AuthenticateError::InsufficientScope`]: ruma::api::client::error::AuthenticateError
use chrono::Utc;
pub use mas_oidc_client::*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that reexport right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reduced it a bit but it's still not ideal, but it avoids to check which types need to be re-exported if we want users not to have to add the crate manually, like we do with Ruma.

The complicated part is that some types use a lot of other types (Verified)ProviderMetadata and (Verified)ClientMetadata among others, so we would have to hunt all the needed types.

It is however doable, if this is really not wanted.

Comment on lines 177 to 179
pub(crate) fn new(client: Client) -> Self {
Self { client }
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit weird to me. Why would we need to carry the Matrix API client? Wouldn't it be enough to configure the OIDC client with issuer + HttpService, and have a method to get one from the Matrix API Client?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I guess it's for consistency with other 'modules' like that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to keep the OIDC data in memory, and until now users only had to keep the Client around so it felt like a simpler API to keep the data in memory inside the Client.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the Timeline API already deviates from this. I'm honestly not too happy with the ever-growing nature of Client. That said if it would be easy to misuse the API otherwise (which I think is not the case for the timeline), let's keep it as-is.

Copy link
Collaborator Author

@zecakeh zecakeh Jun 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to make refreshing tokens transparent, we also need the Client to be able to use this API. Of course we could also make the client keep an Arc<OidcInner> and give an Oidc { inner: Arc<OidcInner>} or something like that.

pub(crate) oidc_data: OnceCell<OidcData>,
/// The data needed to validate an OpenID Connect authorization request.
#[cfg(feature = "experimental-oidc")]
pub(crate) oidc_validation_data: Mutex<HashMap<String, AuthorizationValidationData>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably OK for now, but it feels like it should be stored somewhere else, so that it can be serialized/stored and restored when it goes back to the client. For our use case it's probably fine, the Rust SDK will probably live through the whole flow

In OIDC clients for the browser, this kind of data is stored in the localstorage, and then the state parameter is there to support potentially multiple in-flight authorization, and restore associated parameters (in our case: homeserver, issuer, client registration infos)

@jplatte
Copy link
Collaborator

jplatte commented Jul 31, 2023

We no longer depend on zeroize <1.4 (#2339)! 🎉

As the next step for this PR, can you please rebase?

@zecakeh
Copy link
Collaborator Author

zecakeh commented Aug 4, 2023

The force push was to make a rough rebase on top of #2377. The resulting code in c27440c does not work.

Commit 5853ac3 brings all the new changes.

Most of the TODOs that are left need changes in some of the MAS crates.

@zecakeh zecakeh force-pushed the oidc-mas branch 2 times, most recently from 1a953db to f4ec8ec Compare August 4, 2023 13:47
@zecakeh zecakeh changed the title PoC OIDC experimental: Expose an OpenID Connect API Aug 4, 2023
@zecakeh zecakeh marked this pull request as ready for review August 4, 2023 13:58
@zecakeh zecakeh requested a review from a team as a code owner August 4, 2023 13:58
@zecakeh zecakeh force-pushed the oidc-mas branch 2 times, most recently from 97071c1 to 5853ac3 Compare August 4, 2023 14:10
@codecov
Copy link

codecov bot commented Aug 4, 2023

Codecov Report

Patch coverage: 3.01% and project coverage change: -0.93% ⚠️

Comparison is base (4643bae) 77.97% compared to head (6c58a49) 77.05%.
Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1019      +/-   ##
==========================================
- Coverage   77.97%   77.05%   -0.93%     
==========================================
  Files         177      181       +4     
  Lines       18896    19130     +234     
==========================================
+ Hits        14734    14740       +6     
- Misses       4162     4390     +228     
Files Changed Coverage Δ
crates/matrix-sdk/src/error.rs 63.15% <ø> (ø)
crates/matrix-sdk/src/http_client/mod.rs 75.00% <0.00%> (-8.34%) ⬇️
crates/matrix-sdk/src/lib.rs 100.00% <ø> (ø)
crates/matrix-sdk/src/oidc/auth_code_builder.rs 0.00% <0.00%> (ø)
crates/matrix-sdk/src/oidc/data_serde.rs 0.00% <0.00%> (ø)
crates/matrix-sdk/src/oidc/end_session_builder.rs 0.00% <0.00%> (ø)
crates/matrix-sdk/src/oidc/mod.rs 0.00% <0.00%> (ø)
crates/matrix-sdk/src/client/mod.rs 80.50% <12.50%> (-1.70%) ⬇️
crates/matrix-sdk/src/authentication.rs 40.00% <38.46%> (-20.00%) ⬇️
crates/matrix-sdk/src/matrix_auth/mod.rs 88.07% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@bnjbvr bnjbvr removed the request for review from a team August 10, 2023 12:56
@zecakeh
Copy link
Collaborator Author

zecakeh commented Aug 13, 2023

All the TODOs were handled so it should be good for review again.

@zecakeh zecakeh requested a review from sandhose August 13, 2023 11:49
Comment on lines +123 to +126
/// Set the requested Authentication Context Class Reference values.
///
/// This is only necessary with specific providers.
pub fn acr_values(mut self, acr_values: HashSet<String>) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's "Authentication Context Class Reference", why is the abbreviation acr instead of accr?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, but that's the abbreviation used by OIDC. Also this is the exact name of the field this is supposed to fill.

Signed-off-by: Kévin Commaille <[email protected]>
@jplatte jplatte merged commit 0dac508 into matrix-org:main Aug 16, 2023
@zecakeh zecakeh deleted the oidc-mas branch August 27, 2023 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants