Skip to content
This repository was archived by the owner on Sep 10, 2024. It is now read-only.

Commit 364093f

Browse files
committed
Allow overriding usptream OAuth2 providers endpoints
Also have a way to disable OIDC discovery when all the endpoints are known.
1 parent 08d46a7 commit 364093f

File tree

8 files changed

+609
-31
lines changed

8 files changed

+609
-31
lines changed

crates/data-model/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ pub use self::{
4848
upstream_oauth2::{
4949
UpsreamOAuthProviderSetEmailVerification, UpstreamOAuthAuthorizationSession,
5050
UpstreamOAuthAuthorizationSessionState, UpstreamOAuthLink, UpstreamOAuthProvider,
51-
UpstreamOAuthProviderClaimsImports, UpstreamOAuthProviderImportAction,
52-
UpstreamOAuthProviderImportPreference, UpstreamOAuthProviderSubjectPreference,
51+
UpstreamOAuthProviderClaimsImports, UpstreamOAuthProviderDiscoveryMode,
52+
UpstreamOAuthProviderImportAction, UpstreamOAuthProviderImportPreference,
53+
UpstreamOAuthProviderPkceMode, UpstreamOAuthProviderSubjectPreference,
5354
},
5455
users::{
5556
Authentication, AuthenticationMethod, BrowserSession, Password, User, UserEmail,

crates/data-model/src/upstream_oauth2/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ pub use self::{
2020
link::UpstreamOAuthLink,
2121
provider::{
2222
ClaimsImports as UpstreamOAuthProviderClaimsImports,
23+
DiscoveryMode as UpstreamOAuthProviderDiscoveryMode,
2324
ImportAction as UpstreamOAuthProviderImportAction,
2425
ImportPreference as UpstreamOAuthProviderImportPreference,
26+
PkceMode as UpstreamOAuthProviderPkceMode,
2527
SetEmailVerification as UpsreamOAuthProviderSetEmailVerification,
2628
SubjectPreference as UpstreamOAuthProviderSubjectPreference, UpstreamOAuthProvider,
2729
},

crates/data-model/src/upstream_oauth2/provider.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,45 @@ use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod
1717
use oauth2_types::scope::Scope;
1818
use serde::{Deserialize, Serialize};
1919
use ulid::Ulid;
20+
use url::Url;
21+
22+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
23+
#[serde(rename_all = "lowercase")]
24+
pub enum DiscoveryMode {
25+
/// Use OIDC discovery to fetch and verify the provider metadata
26+
#[default]
27+
Oidc,
28+
29+
/// Use OIDC discovery to fetch the provider metadata, but don't verify it
30+
Insecure,
31+
32+
/// Don't fetch the provider metadata
33+
Disabled,
34+
}
35+
36+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
37+
#[serde(rename_all = "lowercase")]
38+
pub enum PkceMode {
39+
/// Use PKCE if the provider supports it
40+
#[default]
41+
Auto,
42+
43+
/// Always use PKCE with the S256 method
44+
S256,
45+
46+
/// Don't use PKCE
47+
Disabled,
48+
}
2049

2150
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
2251
pub struct UpstreamOAuthProvider {
2352
pub id: Ulid,
2453
pub issuer: String,
54+
pub discovery_mode: DiscoveryMode,
55+
pub pkce_mode: PkceMode,
56+
pub jwks_uri_override: Option<Url>,
57+
pub authorization_endpoint_override: Option<Url>,
58+
pub token_endpoint_override: Option<Url>,
2559
pub scope: Scope,
2660
pub client_id: String,
2761
pub encrypted_client_secret: Option<String>,

crates/handlers/src/upstream_oauth2/authorize.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use mas_storage::{
2929
use thiserror::Error;
3030
use ulid::Ulid;
3131

32-
use super::UpstreamSessionsCookie;
32+
use super::{cache::LazyProviderInfos, UpstreamSessionsCookie};
3333
use crate::{
3434
impl_from_error_for_route, upstream_oauth2::cache::MetadataCache,
3535
views::shared::OptionalPostAuthAction,
@@ -87,23 +87,28 @@ pub(crate) async fn get(
8787
let http_service = http_client_factory.http_service("upstream_oauth2.authorize");
8888

8989
// First, discover the provider
90-
let metadata = metadata_cache.get(&http_service, &provider.issuer).await?;
90+
// This is done lazyly according to provider.discovery_mode and the various
91+
// endpoint overrides
92+
let mut lazy_metadata = LazyProviderInfos::new(&metadata_cache, &provider, &http_service);
93+
lazy_metadata.maybe_discover().await?;
9194

9295
let redirect_uri = url_builder.upstream_oauth_callback(provider.id);
9396

94-
let mut data = AuthorizationRequestData::new(
97+
let data = AuthorizationRequestData::new(
9598
provider.client_id.clone(),
9699
provider.scope.clone(),
97100
redirect_uri,
98101
);
99102

100-
if let Some(methods) = metadata.code_challenge_methods_supported.clone() {
101-
data = data.with_code_challenge_methods_supported(methods);
102-
}
103+
let data = if let Some(methods) = lazy_metadata.pkce_methods().await? {
104+
data.with_code_challenge_methods_supported(methods)
105+
} else {
106+
data
107+
};
103108

104109
// Build an authorization request for it
105110
let (url, data) = mas_oidc_client::requests::authorization_code::build_authorization_url(
106-
metadata.authorization_endpoint().clone(),
111+
lazy_metadata.authorization_endpoint().await?.clone(),
107112
data,
108113
&mut rng,
109114
)?;

0 commit comments

Comments
 (0)