Skip to content

allow account linking for existing users when the localpart matches in upstream OAuth 2.0 logins #4193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/cli/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ pub async fn config_sync(
fetch_userinfo: provider.fetch_userinfo,
userinfo_signed_response_alg: provider.userinfo_signed_response_alg,
response_mode,
allow_existing_users: provider.allow_existing_users,
additional_authorization_parameters: provider
.additional_authorization_parameters
.into_iter()
Expand Down
19 changes: 19 additions & 0 deletions crates/config/src/sections/upstream_oauth2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ impl ConfigurationSection for UpstreamOAuth2Config {
}
}
}

if provider.allow_existing_users
&& !matches!(
provider.claims_imports.localpart.action,
ImportAction::Force | ImportAction::Require
)
{
return annotate(figment::Error::custom(
"When `allow_existing_users` is true, localpart claim import must be either `force` or `require`",
));
}
}

Ok(())
Expand Down Expand Up @@ -411,6 +422,7 @@ fn is_default_scope(scope: &str) -> bool {
/// Configuration for one upstream OAuth 2 provider.
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[allow(clippy::struct_excessive_bools)]
pub struct Provider {
/// Whether this provider is enabled.
///
Expand Down Expand Up @@ -571,6 +583,13 @@ pub struct Provider {
#[serde(default, skip_serializing_if = "ClaimsImports::is_default")]
pub claims_imports: ClaimsImports,

/// Whether to allow a user logging in via OIDC to match a pre-existing
/// account instead of failing. This could be used if switching from
/// password logins to OIDC.
//Defaults to false.
#[serde(default)]
pub allow_existing_users: bool,

/// Additional parameters to include in the authorization request
///
/// Orders of the keys are not preserved.
Expand Down
1 change: 1 addition & 0 deletions crates/data-model/src/upstream_oauth2/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ pub struct UpstreamOAuthProvider {
pub created_at: DateTime<Utc>,
pub disabled_at: Option<DateTime<Utc>>,
pub claims_imports: ClaimsImports,
pub allow_existing_users: bool,
pub additional_authorization_parameters: Vec<(String, String)>,
pub forward_login_hint: bool,
}
Expand Down
1 change: 1 addition & 0 deletions crates/handlers/src/admin/v1/upstream_oauth_links/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mod test_utils {
token_endpoint_override: None,
userinfo_endpoint_override: None,
jwks_uri_override: None,
allow_existing_users: true,
additional_authorization_parameters: Vec::new(),
forward_login_hint: false,
ui_order: 0,
Expand Down
1 change: 1 addition & 0 deletions crates/handlers/src/upstream_oauth2/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ mod tests {
created_at: clock.now(),
disabled_at: None,
claims_imports: UpstreamOAuthProviderClaimsImports::default(),
allow_existing_users: false,
additional_authorization_parameters: Vec::new(),
forward_login_hint: false,
};
Expand Down
Loading
Loading