Пример #1
0
    def pre_social_login(self, request, sociallogin):
        """
        Retrieve and verify (again) auth token that was provided with initial connect request.  Store as request.user,
        as required for socialauth connect logic.
        """
        self._update_session(request, sociallogin)
        try:
            authcode = get_session_authcode(request)
            if authcode is not None:
                accesstoken = accesstoken_for_authcode(authcode)
                if not accesstoken:
                    raise ImmediateHttpResponse(HttpResponseForbidden())

                request.user = accesstoken.user
                if sociallogin.is_existing and accesstoken.user != sociallogin.user:
                    badgr_app = get_session_badgr_app(self.request)
                    redirect_url = "{url}?authError={message}".format(
                        url=badgr_app.ui_connect_success_redirect,
                        message=urllib.quote(
                            "Could not add social login. This account is already associated with a user."
                        ))
                    raise ImmediateHttpResponse(
                        HttpResponseRedirect(redirect_to=redirect_url))
        except AuthenticationFailed as e:
            raise ImmediateHttpResponse(HttpResponseForbidden(e.detail))
Пример #2
0
    def get_redirect_url(self, *args, **kwargs):
        authcode = self.request.GET.get('authcode',
                                        get_session_authcode(self.request))
        if not authcode:
            return saml2_fail(authError="Could not complete Saml login")

        accesstoken = accesstoken_for_authcode(authcode)
        return redirect_to_login_with_token(self.request, accesstoken)
Пример #3
0
    def post(self, request, **kwargs):
        def _error_response():
            return Response({"error": "Invalid authcode"},
                            status=HTTP_400_BAD_REQUEST)

        code = request.data.get('code')
        if not code:
            return _error_response()

        accesstoken = accesstoken_for_authcode(code)
        if accesstoken is None:
            return _error_response()

        data = dict(access_token=accesstoken.token,
                    token_type="Bearer",
                    scope=accesstoken.scope)

        return Response(data, status=HTTP_200_OK)
Пример #4
0
    def post(self, request, **kwargs):
        def _error_response():
            return Response({"error": "Invalid authcode"}, status=HTTP_400_BAD_REQUEST)

        code = request.data.get('code')
        if not code:
            return _error_response()

        accesstoken = accesstoken_for_authcode(code)
        if accesstoken is None:
            return _error_response()

        data = dict(
            access_token=accesstoken.token,
            token_type="Bearer",
            scope=accesstoken.scope
        )

        return Response(data, status=HTTP_200_OK)
Пример #5
0
    def get_redirect_url(self, *args, **kwargs):
        authcode = get_session_authcode(self.request)
        accesstoken = accesstoken_for_authcode(authcode)

        try:
            data = json.loads(decrypt_authcode(self.request.GET['request_id']))
            client, config = saml2_client_for(data['idp_name'])
            email = data['email']
            first_name = data['first_name']
            last_name = data['last_name']

        except (
                TypeError,
                ValueError,
                AttributeError,
                KeyError,
                Saml2Configuration.DoesNotExist,
        ) as e:
            return saml2_fail(authError="Could not process Saml2 Response.")

        try:
            existing_email = CachedEmailAddress.cached.get(email=email)
        except CachedEmailAddress.DoesNotExist:
            if accesstoken is not None and not accesstoken.is_expired():
                saml2_account = Saml2Account.objects.create(
                    config=config, user=accesstoken.user, uuid=email)
                new_mail = CachedEmailAddress.objects.create(
                    email=email,
                    user=accesstoken.user,
                    verified=True,
                    primary=False)
                return redirect_to_login_with_token(self.request, accesstoken)

            # Email does not exist, nor does existing account. auto-provision new account and log in
            return redirect_user_to_login(
                saml2_new_account(email, config, first_name, last_name,
                                  self.request))

        else:
            return saml2_fail(
                authError="Saml2 Response Processing interrupted. Email exists."
            )
Пример #6
0
    def pre_social_login(self, request, sociallogin):
        """
        Retrieve and verify (again) auth token that was provided with initial connect request.  Store as request.user,
        as required for socialauth connect logic.
        """
        self._update_session(request, sociallogin)
        try:
            authcode = get_session_authcode(request)
            if authcode is not None:
                accesstoken = accesstoken_for_authcode(authcode)
                if not accesstoken:
                    raise ImmediateHttpResponse(HttpResponseForbidden())

                request.user = accesstoken.user
                if sociallogin.is_existing and accesstoken.user != sociallogin.user:
                    badgr_app = get_session_badgr_app(self.request)
                    redirect_url = "{url}?authError={message}".format(
                        url=badgr_app.ui_connect_success_redirect,
                        message=urllib.quote("Could not add social login. This account is already associated with a user."))
                    raise ImmediateHttpResponse(HttpResponseRedirect(redirect_to=redirect_url))
        except AuthenticationFailed as e:
            raise ImmediateHttpResponse(HttpResponseForbidden(e.detail))
Пример #7
0
    def get_redirect_url(self, *args, **kwargs):
        self.badgr_app = BadgrApp.objects.get_current(self.request)

        # Override: user has an appropriate authcode for the return flight to the UI
        authcode = get_session_authcode(self.request)
        email = self.request.GET.get('email')
        idp_name = self.request.session.get('idp_name')

        if not email or not authcode or not idp_name:
            return saml2_fail(
                authError=
                "Could not associate SAML response with initial request",
                email=email,
                socialAuthSlug=idp_name)

        saml_client, config = saml2_client_for(idp_name)

        decoded_email = base64.urlsafe_b64decode(email).decode('utf-8')
        existing_email = CachedEmailAddress.cached.get(email=decoded_email)
        token = accesstoken_for_authcode(authcode)
        if token is not None and not token.is_expired(
        ) and token.user == existing_email.user:
            saml2_account = Saml2Account.objects.create(
                config=config, user=existing_email.user, uuid=decoded_email)
            return redirect_user_to_login(saml2_account.user)
        elif token is not None and token.is_expired():
            return saml2_fail(
                authError='Request is expired. Please try again.',
                email=email,
                socialAuthSlug=idp_name)

        # Fail: user does not have an appropriate authcode
        return saml2_fail(
            authError='An account already exists with provided email address',
            email=email,
            socialAuthSlug=idp_name)
Пример #8
0
def auto_provision(request, email, first_name, last_name, badgr_app, config,
                   idp_name):
    def login(user, token=None):
        if token is not None and not token.is_expired():
            accesstoken = token
        else:
            accesstoken = AccessTokenProxy.objects.generate_new_token_for_user(
                user, scope='rw:backpack rw:profile rw:issuer')

        if badgr_app.use_auth_code_exchange:
            authcode = authcode_for_accesstoken(accesstoken)
            params = dict(authCode=authcode)
        else:
            params = dict(authToken=accesstoken.token)
        return redirect(
            set_url_query_params(badgr_app.ui_login_redirect, **params))

    def new_account(requested_email):
        new_user = BadgeUser.objects.create(email=requested_email,
                                            first_name=first_name,
                                            last_name=last_name,
                                            request=request,
                                            send_confirmation=False)
        # Auto verify emails
        cached_email = CachedEmailAddress.objects.get(email=requested_email)
        cached_email.verified = True
        cached_email.save()
        Saml2Account.objects.create(config=config,
                                    user=new_user,
                                    uuid=requested_email)
        return new_user

    # Get/Create account and redirect with token or with error message
    saml2_account = Saml2Account.objects.filter(uuid=email,
                                                config=config).first()
    if saml2_account:
        return login(saml2_account.user)

    try:
        existing_email = CachedEmailAddress.cached.get(email=email)
        if not existing_email.verified:
            # Email exists but is not verified, auto-provision account and log in
            new_account = new_account(email)
            return login(new_account)
        elif existing_email.verified:
            # Email exists and is already verified

            # Override: user has an appropriate authcode for the return flight to the UI
            authcode = get_session_authcode(request)
            if authcode is not None:
                token = accesstoken_for_authcode(authcode)
                if token is not None and not token.is_expired(
                ) and token.user == existing_email.user:
                    saml2_account = Saml2Account.objects.create(
                        config=config, user=existing_email.user, uuid=email)
                    return login(saml2_account.user, token)

            # Fail: user does not have an appropriate authcode
            url = set_url_query_params(
                badgr_app.ui_signup_failure_redirect,
                authError=
                'An account already exists with provided email address',
                email=str(base64.urlsafe_b64encode(email.encode('utf-8')),
                          'utf'),
                socialAuthSlug=idp_name)
            return redirect(url)
    except CachedEmailAddress.DoesNotExist:
        authcode = get_session_authcode(request)
        if authcode is not None:
            token = accesstoken_for_authcode(authcode)
            if token is not None and not token.is_expired():
                saml2_account = Saml2Account.objects.create(config=config,
                                                            user=token.user,
                                                            uuid=email)
                new_mail = CachedEmailAddress.objects.create(email=email,
                                                             user=token.user,
                                                             verified=True,
                                                             primary=False)
                return login(saml2_account.user, token)

        # Email does not exist, nor does existing account. auto-provision new account and log in
        return login(new_account(email))