saml: Add setting to skip the "continue to registration" page.

It's a smoother Just-In-Time provisioning process to allow
creating the account and getting signed in on the first login by the
user.
This commit is contained in:
Mateusz Mandera 2021-06-13 14:18:28 +02:00 committed by Tim Abbott
parent d2074fc10c
commit 3b4f8cc85b
4 changed files with 57 additions and 1 deletions

View File

@ -400,6 +400,8 @@ it as follows:
user ID) and name for the user.
5. The `display_name` and `display_icon` fields are used to
display the login/registration buttons for the IdP.
6. The `auto_signup` field determines how Zulip should handle
login attempts by users who don't have an account yet.
1. Install the certificate(s) required for SAML authentication. You
will definitely need the public certificate of your IdP. Some IdP

View File

@ -1945,6 +1945,39 @@ class SAMLAuthBackendTest(SocialAuthBase):
result,
)
@override_settings(TERMS_OF_SERVICE=None)
def test_social_auth_registration_auto_signup(self) -> None:
"""
Verify that with SAML auto signup enabled, a user coming from the /login page
(so without the is_signup param) will be taken straight to registration, without
having to go through the step of having to confirm that they do want to sign up.
"""
email = "newuser@zulip.com"
name = "Full Name"
subdomain = "zulip"
realm = get_realm("zulip")
account_data_dict = self.get_account_data_dict(email=email, name=name)
idps_dict = copy.deepcopy(settings.SOCIAL_AUTH_SAML_ENABLED_IDPS)
idps_dict["test_idp"]["auto_signup"] = True
with self.settings(SOCIAL_AUTH_SAML_ENABLED_IDPS=idps_dict):
result = self.social_auth_test(
account_data_dict,
expect_choose_email_screen=True,
subdomain=subdomain,
is_signup=False,
)
self.stage_two_of_registration(
result,
realm,
subdomain,
email,
name,
name,
self.BACKEND_CLASS.full_name_validated,
expect_confirm_registration_page=False,
)
def test_social_auth_complete(self) -> None:
with mock.patch.object(OneLogin_Saml2_Response, "is_valid", return_value=True):
with mock.patch.object(

View File

@ -1560,7 +1560,7 @@ def social_auth_finish(
validate_otp_params(mobile_flow_otp, desktop_flow_otp)
if user_profile is None or user_profile.is_mirror_dummy:
is_signup = strategy.session_get("is_signup") == "1"
is_signup = strategy.session_get("is_signup") == "1" or backend.should_auto_signup()
else:
is_signup = False
@ -1675,6 +1675,9 @@ class SocialAuthMixin(ZulipAuthMixin, ExternalAuthMethod, BaseAuth):
self.logger.warning(str(e))
return None
def should_auto_signup(self) -> bool:
return False
@classmethod
def dict_representation(cls, realm: Optional[Realm] = None) -> List[ExternalAuthMethodDictT]:
return [
@ -2271,6 +2274,9 @@ class SAMLAuthBackend(SocialAuthMixin, SAMLAuth):
if param in self.standard_relay_params:
self.strategy.session_set(param, value)
# We want the IdP name to be accessible from the social pipeline.
self.strategy.session_set("saml_idp_name", idp_name)
# super().auth_complete expects to have RelayState set to the idp_name,
# so we need to replace this param.
post_params = self.strategy.request.POST.copy()
@ -2339,6 +2345,15 @@ class SAMLAuthBackend(SocialAuthMixin, SAMLAuth):
return result
def should_auto_signup(self) -> bool:
"""
This function is meant to be called in the social pipeline or later,
as it requires (validated) information about the IdP name to have
already been store in the session.
"""
idp_name = self.strategy.session_get("saml_idp_name")
return settings.SOCIAL_AUTH_SAML_ENABLED_IDPS[idp_name].get("auto_signup", False)
@external_auth_method
class GenericOpenIdConnectBackend(SocialAuthMixin, OpenIdConnectAuth):

View File

@ -438,6 +438,12 @@ SOCIAL_AUTH_SAML_ENABLED_IDPS: Dict[str, Any] = {
## You can also limit subdomains by setting "attr_org_membership"
## to be a SAML attribute containing the allowed subdomains for a user.
# "attr_org_membership": "member",
##
## Determines whether "Log in with SAML" will automatically
## register a new account if one does not already exist. By
## default, Zulip asks the user whether they want to create an
## account or try to log in again using another method.
# "auto_signup": False,
},
}