Add option for trusted providers to associate with existing accounts. (fixes #252)
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -636,14 +636,14 @@ async fn decide_user_id(
|
||||
];
|
||||
|
||||
for choice in choices.into_iter().flatten() {
|
||||
if let Some(user_id) = try_user_id(services, &choice, false).await {
|
||||
if let Some(user_id) = try_user_id(services, provider, &choice, false).await {
|
||||
return Ok(user_id);
|
||||
}
|
||||
}
|
||||
|
||||
let length = Some(15..23);
|
||||
let unique_id = truncate_deterministic(unique_id, length).to_lowercase();
|
||||
if let Some(user_id) = try_user_id(services, &unique_id, true).await {
|
||||
if let Some(user_id) = try_user_id(services, provider, &unique_id, true).await {
|
||||
return Ok(user_id);
|
||||
}
|
||||
|
||||
@@ -653,8 +653,9 @@ async fn decide_user_id(
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(username))]
|
||||
async fn try_user_id(
|
||||
services: &Services,
|
||||
provider: &Provider,
|
||||
username: &str,
|
||||
may_exist: bool,
|
||||
unique_id: bool,
|
||||
) -> Option<OwnedUserId> {
|
||||
let server_name = services.globals.server_name();
|
||||
let user_id = parse_user_id(server_name, username)
|
||||
@@ -671,7 +672,15 @@ async fn try_user_id(
|
||||
}
|
||||
|
||||
if services.users.exists(&user_id).await {
|
||||
debug_warn!(?username, "Username exists.");
|
||||
if provider.trusted {
|
||||
info!(
|
||||
?username,
|
||||
provider = ?provider.brand,
|
||||
"Authorizing trusted provider access to existing account."
|
||||
);
|
||||
|
||||
return Some(user_id);
|
||||
}
|
||||
|
||||
if services
|
||||
.users
|
||||
@@ -680,11 +689,12 @@ async fn try_user_id(
|
||||
.ok()
|
||||
.is_none_or(|origin| origin != "sso")
|
||||
{
|
||||
debug_warn!(?username, "Username has non-sso origin.");
|
||||
debug_warn!(?username, "Existing username has non-sso origin.");
|
||||
return None;
|
||||
}
|
||||
|
||||
if !may_exist {
|
||||
if !unique_id {
|
||||
debug_warn!(?username, "Username exists.");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2741,6 +2741,25 @@ pub struct IdentityProvider {
|
||||
#[serde(default)]
|
||||
pub userid_claims: BTreeSet<String>,
|
||||
|
||||
/// Trusted providers can cause username conflicts (i.e. account hijacking)
|
||||
/// but this is precisely how an existing matrix account can be associated
|
||||
/// with a provider. When this option is set to true, the way we compute a
|
||||
/// Matrix UserId from userinfo claims is inverted: we find the first
|
||||
/// matching user and grant access to it. Whereas by default, when set to
|
||||
/// false, we skip matching users and register the first available username;
|
||||
/// falling-back to random characters to avoid conflicts.
|
||||
///
|
||||
/// Only set this option to true for providers you self-host and control.
|
||||
/// Never set this option to true for the public providers such as GitHub,
|
||||
/// GitLab, etc.
|
||||
///
|
||||
/// Note that associating an existing user with an untrusted provider is
|
||||
/// still possible but only with the command '!admin query oauth associate'.
|
||||
///
|
||||
/// default: false
|
||||
#[serde(default)]
|
||||
pub trusted: bool,
|
||||
|
||||
/// Optional extra path components after the issuer_url leading to the
|
||||
/// location of the `.well-known` directory used for discovery. If the path
|
||||
/// starts with a slash it will be treated as absolute, meaning overwriting
|
||||
|
||||
@@ -2343,6 +2343,23 @@
|
||||
#
|
||||
#userid_claims = []
|
||||
|
||||
# Trusted providers can cause username conflicts (i.e. account hijacking)
|
||||
# but this is precisely how an existing matrix account can be associated
|
||||
# with a provider. When this option is set to true, the way we compute a
|
||||
# Matrix UserId from userinfo claims is inverted: we find the first
|
||||
# matching user and grant access to it. Whereas by default, when set to
|
||||
# false, we skip matching users and register the first available username;
|
||||
# falling-back to random characters to avoid conflicts.
|
||||
#
|
||||
# Only set this option to true for providers you self-host and control.
|
||||
# Never set this option to true for the public providers such as GitHub,
|
||||
# GitLab, etc.
|
||||
#
|
||||
# Note that associating an existing user with an untrusted provider is
|
||||
# still possible but only with the command '!admin query oauth associate'.
|
||||
#
|
||||
#trusted = false
|
||||
|
||||
# Optional extra path components after the issuer_url leading to the
|
||||
# location of the `.well-known` directory used for discovery. If the path
|
||||
# starts with a slash it will be treated as absolute, meaning overwriting
|
||||
|
||||
Reference in New Issue
Block a user