From febf4a930ede76a5487377c1075d1971d5735ed2 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Thu, 30 Apr 2026 15:08:59 +0200 Subject: [PATCH] Treat OIDC and magic link sessions as password-equivalent when assuming an org Users authenticated via Google/Microsoft OIDC or magic link previously relied on a fall-through in the password-only org check. Make the rule explicit so SSO-only users can access password-only organizations without being bounced to the password login form they cannot satisfy. Signed-off-by: Bryan Frimin --- pkg/iam/session_service.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/pkg/iam/session_service.go b/pkg/iam/session_service.go index edb493d4f..aeae3bcf7 100644 --- a/pkg/iam/session_service.go +++ b/pkg/iam/session_service.go @@ -566,14 +566,25 @@ func (s SessionService) AssumeOrganizationSession( return NewSAMLAuthenticationRequiredError("policy_requirement") } case coredata.SAMLEnforcementPolicyOptional: - // SAML is optional: both PASSWORD and SAML root sessions are allowed. + // SAML is optional: any password-equivalent (PASSWORD, OIDC, + // MAGIC_LINK) or SAML root session is allowed. } } else { switch rootSession.AuthMethod { - case coredata.AuthMethodPassword: + case coredata.AuthMethodPassword, + coredata.AuthMethodOIDC, + coredata.AuthMethodMagicLink: + // No SAML configuration for this org+domain: any + // password-equivalent root session is allowed. OIDC + // (Google / Microsoft) and magic-link logins are treated + // as password logins because the user has authenticated + // against the platform itself rather than a third-party + // IdP federated with this organization. case coredata.AuthMethodSAML: - // No (or non-required) SAML configuration: require a password-authenticated or magic-link root session - // (eg. when switching into a password-based org from a SAML login) + // SAML root sessions are bound to a different organization's + // IdP, so they cannot be used to access an organization that + // does not federate with that IdP. Force re-authentication + // with a password-equivalent method. return NewPasswordAuthenticationRequiredError("password_authentication_required") } }