Exemple #1
0
def start_social_login(
    request: HttpRequest,
    backend: str,
    extra_arg: Optional[str] = None,
) -> HttpResponse:
    backend_url = reverse('social:begin', args=[backend])
    extra_url_params: Dict[str, str] = {}
    if backend == "saml":
        result = SAMLAuthBackend.check_config()
        if result is not None:
            return result

        # This backend requires the name of the IdP (from the list of configured ones)
        # to be passed as the parameter.
        if not extra_arg or extra_arg not in settings.SOCIAL_AUTH_SAML_ENABLED_IDPS:
            logging.info(
                "Attempted to initiate SAML authentication with wrong idp argument: %s",
                extra_arg)
            return redirect_to_config_error("saml")
        extra_url_params = {'idp': extra_arg}

    # TODO: Add AzureAD also.
    if backend in ["github", "google", "gitlab", "apple"]:
        key_setting = "SOCIAL_AUTH_" + backend.upper() + "_KEY"
        secret_setting = "SOCIAL_AUTH_" + backend.upper() + "_SECRET"
        if not (getattr(settings, key_setting)
                and getattr(settings, secret_setting)):
            return redirect_to_config_error(backend)

    return oauth_redirect_to_root(request,
                                  backend_url,
                                  'social',
                                  extra_url_params=extra_url_params)
Exemple #2
0
def start_social_login(request: HttpRequest,
                       backend: str,
                       extra_arg: Optional[str] = None) -> HttpResponse:
    backend_url = reverse('social:begin', args=[backend])
    extra_url_params = {}  # type: Dict[str, str]
    if backend == "saml":
        result = SAMLAuthBackend.check_config()
        if result is not None:
            return result

        # This backend requires the name of the IdP (from the list of configured ones)
        # to be passed as the parameter.
        if not extra_arg or extra_arg not in settings.SOCIAL_AUTH_SAML_ENABLED_IDPS:
            logging.info(
                "Attempted to initiate SAML authentication with wrong idp argument: {}"
                .format(extra_arg))
            return redirect_to_config_error("saml")
        extra_url_params = {'idp': extra_arg}
    if (backend == "github") and not (settings.SOCIAL_AUTH_GITHUB_KEY
                                      and settings.SOCIAL_AUTH_GITHUB_SECRET):
        return redirect_to_config_error("github")
    if (backend == "google") and not (settings.SOCIAL_AUTH_GOOGLE_KEY
                                      and settings.SOCIAL_AUTH_GOOGLE_SECRET):
        return redirect_to_config_error("google")
    if (backend == "gitlab") and not (settings.SOCIAL_AUTH_GITLAB_KEY
                                      and settings.SOCIAL_AUTH_GITLAB_SECRET):
        return redirect_to_config_error("gitlab")
    # TODO: Add a similar block for AzureAD.

    return oauth_redirect_to_root(request,
                                  backend_url,
                                  'social',
                                  extra_url_params=extra_url_params)
Exemple #3
0
def remote_user_sso(
        request: HttpRequest,
        mobile_flow_otp: Optional[str] = REQ(default=None),
        desktop_flow_otp: Optional[str] = REQ(default=None),
        next: str = REQ(default="/"),
) -> HttpResponse:
    subdomain = get_subdomain(request)
    try:
        realm: Optional[Realm] = get_realm(subdomain)
    except Realm.DoesNotExist:
        realm = None

    if not auth_enabled_helper([ZulipRemoteUserBackend.auth_backend_name],
                               realm):
        return redirect_to_config_error("remoteuser/backend_disabled")

    try:
        remote_user = request.META["REMOTE_USER"]
    except KeyError:
        return redirect_to_config_error(
            "remoteuser/remote_user_header_missing")

    # Django invokes authenticate methods by matching arguments, and this
    # authentication flow will not invoke LDAP authentication because of
    # this condition of Django so no need to check if LDAP backend is
    # enabled.
    validate_login_email(remote_user_to_email(remote_user))

    # Here we support the mobile and desktop flow for REMOTE_USER_BACKEND; we
    # validate the data format and then pass it through to
    # login_or_register_remote_user if appropriate.
    validate_otp_params(mobile_flow_otp, desktop_flow_otp)

    if realm is None:
        user_profile = None
    else:
        user_profile = authenticate(remote_user=remote_user, realm=realm)

    email = remote_user_to_email(remote_user)
    data_dict = ExternalAuthDataDict(
        email=email,
        mobile_flow_otp=mobile_flow_otp,
        desktop_flow_otp=desktop_flow_otp,
        redirect_to=next,
    )
    if realm:
        data_dict["subdomain"] = realm.subdomain
    else:
        data_dict["subdomain"] = ''  # realm creation happens on root subdomain
    result = ExternalAuthResult(user_profile=user_profile, data_dict=data_dict)
    return login_or_register_remote_user(request, result)
Exemple #4
0
def remote_user_sso(
    request: HttpRequest,
    mobile_flow_otp: Optional[str] = REQ(default=None),
    desktop_flow_otp: Optional[str] = REQ(default=None)
) -> HttpResponse:
    subdomain = get_subdomain(request)
    try:
        realm = get_realm(subdomain)  # type: Optional[Realm]
    except Realm.DoesNotExist:
        realm = None

    if not auth_enabled_helper([ZulipRemoteUserBackend.auth_backend_name],
                               realm):
        return redirect_to_config_error("remoteuser/backend_disabled")

    try:
        remote_user = request.META["REMOTE_USER"]
    except KeyError:
        return redirect_to_config_error(
            "remoteuser/remote_user_header_missing")

    # Django invokes authenticate methods by matching arguments, and this
    # authentication flow will not invoke LDAP authentication because of
    # this condition of Django so no need to check if LDAP backend is
    # enabled.
    validate_login_email(remote_user_to_email(remote_user))

    # Here we support the mobile and desktop flow for REMOTE_USER_BACKEND; we
    # validate the data format and then pass it through to
    # login_or_register_remote_user if appropriate.
    validate_otp_params(mobile_flow_otp, desktop_flow_otp)

    subdomain = get_subdomain(request)
    if realm is None:
        user_profile = None
    else:
        user_profile = authenticate(remote_user=remote_user, realm=realm)

    redirect_to = request.GET.get('next', '')

    return login_or_register_remote_user(request,
                                         remote_user,
                                         user_profile,
                                         mobile_flow_otp=mobile_flow_otp,
                                         desktop_flow_otp=desktop_flow_otp,
                                         realm=realm,
                                         redirect_to=redirect_to)
Exemple #5
0
def dev_direct_login(request: HttpRequest, **kwargs: Any) -> HttpResponse:
    # This function allows logging in without a password and should only be called
    # in development environments.  It may be called if the DevAuthBackend is included
    # in settings.AUTHENTICATION_BACKENDS
    if (not dev_auth_enabled()) or settings.PRODUCTION:
        # This check is probably not required, since authenticate would fail without
        # an enabled DevAuthBackend.
        return redirect_to_config_error('dev')
    email = request.POST['direct_email']
    subdomain = get_subdomain(request)
    realm = get_realm(subdomain)
    user_profile = authenticate(dev_auth_username=email, realm=realm)
    if user_profile is None:
        return redirect_to_config_error('dev')
    do_login(request, user_profile)

    next = request.GET.get('next', '')
    redirect_to = get_safe_redirect_to(next, user_profile.realm.uri)
    return HttpResponseRedirect(redirect_to)
Exemple #6
0
def start_social_login(request: HttpRequest,
                       backend: str,
                       extra_arg: Optional[str] = None) -> HttpResponse:
    user_agent = parse_user_agent(
        request.META.get("HTTP_USER_AGENT", "Missing User-Agent"))
    if user_agent["name"] == "ZulipElectron":
        return render(request, "zerver/desktop_login.html")

    backend_url = reverse('social:begin', args=[backend])
    extra_url_params: Dict[str, str] = {}
    if backend == "saml":
        result = SAMLAuthBackend.check_config()
        if result is not None:
            return result

        # This backend requires the name of the IdP (from the list of configured ones)
        # to be passed as the parameter.
        if not extra_arg or extra_arg not in settings.SOCIAL_AUTH_SAML_ENABLED_IDPS:
            logging.info(
                "Attempted to initiate SAML authentication with wrong idp argument: {}"
                .format(extra_arg))
            return redirect_to_config_error("saml")
        extra_url_params = {'idp': extra_arg}

    # TODO: Add AzureAD also.
    if backend in ["github", "google", "gitlab"]:
        key_setting = "SOCIAL_AUTH_" + backend.upper() + "_KEY"
        secret_setting = "SOCIAL_AUTH_" + backend.upper() + "_SECRET"
        if not (getattr(settings, key_setting)
                and getattr(settings, secret_setting)):
            return redirect_to_config_error(backend)

    return oauth_redirect_to_root(request,
                                  backend_url,
                                  'social',
                                  extra_url_params=extra_url_params)
Exemple #7
0
def start_social_signup(request: HttpRequest, backend: str, extra_arg: Optional[str]=None
                        ) -> HttpResponse:
    backend_url = reverse('social:begin', args=[backend])
    extra_url_params = {}  # type: Dict[str, str]
    if backend == "saml":
        result = SAMLAuthBackend.check_config()
        if result is not None:
            return result

        if not extra_arg or extra_arg not in settings.SOCIAL_AUTH_SAML_ENABLED_IDPS:
            logging.info("Attempted to initiate SAML authentication with wrong idp argument: {}"
                         .format(extra_arg))
            return redirect_to_config_error("saml")
        extra_url_params = {'idp': extra_arg}
    return oauth_redirect_to_root(request, backend_url, 'social', is_signup=True,
                                  extra_url_params=extra_url_params)
Exemple #8
0
def saml_sp_metadata(request: HttpRequest,
                     **kwargs: Any) -> HttpResponse:  # nocoverage
    """
    This is the view function for generating our SP metadata
    for SAML authentication. It's meant for helping check the correctness
    of the configuration when setting up SAML, or for obtaining the XML metadata
    if the IdP requires it.
    Taken from https://python-social-auth.readthedocs.io/en/latest/backends/saml.html
    """
    if not saml_auth_enabled():
        return redirect_to_config_error("saml")

    complete_url = reverse('social:complete', args=("saml", ))
    saml_backend = load_backend(load_strategy(request), "saml", complete_url)
    metadata, errors = saml_backend.generate_metadata_xml()
    if not errors:
        return HttpResponse(content=metadata, content_type='text/xml')

    return HttpResponseServerError(content=', '.join(errors))
Exemple #9
0
def redirect_to_misconfigured_ldap_notice(error_type: int) -> HttpResponse:
    if error_type == ZulipLDAPAuthBackend.REALM_IS_NONE_ERROR:
        return redirect_to_config_error('ldap')
    else:
        raise AssertionError("Invalid error type")