Example #1
0
    def test_bad_key(self):
        """
        Providing a bad key will always cause the user to have to
        log back into their account.

        Bad keys are defined as providing a key that doesn't match the
        user's current key or providing a key when the user doesn't currently
        have a key defined.
        """
        # no key
        no_key = self.key_qs % (self.auth_callback, AuthorizedClient.create_key(self.user))
        response = self.client.get(reverse("sso_authorize") + no_key)
        self.assertEqual(AuthorizedClient.objects.count(), 0)

        # Ensure that user was logged out
        response = self.client.get(reverse("view_profile"))
        path = response.request.get("PATH_INFO")
        self.assertRedirects(response, reverse("home") + "?next=" + path)

        # wrong key
        self.client.login_user(self.user)
        session = self.client.session
        session["key"] = AuthorizedClient.create_key(self.user)
        session.save()

        # key is a hex string; we can invalidate it by taking a substring
        wrong_key = self.key_qs % (self.auth_callback, AuthorizedClient.create_key(self.user)[:-1])

        AuthorizedClientFactory(user=self.user)

        response = self.client.get(reverse("sso_authorize") + wrong_key)
        # Ensure that user was logged out again
        response = self.client.get(reverse("view_profile"))
        path = response.request.get("PATH_INFO")
        self.assertRedirects(response, reverse("home") + "?next=" + path)
Example #2
0
    def test_bad_key(self):
        """
        Providing a bad key will always cause the user to have to
        log back into their account.

        Bad keys are defined as providing a key that doesn't match the
        user's current key or providing a key when the user doesn't currently
        have a key defined.
        """
        # no key
        no_key = self.key_qs % (self.auth_callback,
                                AuthorizedClient.create_key(self.user))
        response = self.client.get(reverse('sso_authorize') + no_key)
        self.assertEqual(AuthorizedClient.objects.count(), 0)

        # Ensure that user was logged out
        response = self.client.get(reverse('view_profile'))
        path = response.request.get('PATH_INFO')
        self.assertRedirects(response, reverse('home')+'?next='+path)

        # wrong key
        self.client.login_user(self.user)
        session = self.client.session
        session['key'] = AuthorizedClient.create_key(self.user)
        session.save()

        # key is a hex string; we can invalidate it by taking a substring
        wrong_key = self.key_qs % (self.auth_callback,
                                   AuthorizedClient.create_key(self.user)[:-1])

        AuthorizedClientFactory(user=self.user)

        response = self.client.get(reverse('sso_authorize') + wrong_key)
        # Ensure that user was logged out again
        response = self.client.get(reverse('view_profile'))
        path = response.request.get('PATH_INFO')
        self.assertRedirects(response, reverse('home')+'?next='+path)
Example #3
0
def sso_authorize(request):
    """
    Authorizes specific web sites to utilize an existing My.jobs account

    Required on HTTP GET:
    :auth_callback: GET parameter - Desired return url when authorization
        succeeds

    Required on HTTP POST:
    :auth_callback: POST parameter, copy of :auth_callback: GET parameter
    """
    # Common between GET and POST, callback is required.
    auth_callback = request.GET.get('auth_callback') or \
        request.POST.get('auth_callback')
    data = {'auth_callback': auth_callback}

    if auth_callback:
        auth_callback = unquote(auth_callback)
        auth_callback = urlparse.urlparse(auth_callback)
        if not auth_callback.netloc:
            # If the base url of the callback is not truthy, the url
            # must be malformed somehow
            raise Http404
    else:
        raise Http404

    if request.method == 'GET':
        # Initial view after being redirected from an external site
        data['auth_callback_short'] = auth_callback.netloc

        if not request.user.is_anonymous():
            # Process logged in users first; Certain criteria may cause the
            # user to be logged out.
            good_key = request.session.get('key')
            test_key = request.GET.get('key')
            if good_key:
                # The current user already has a key available.
                if test_key:
                    # The remote site has provided a key; the user has
                    # potentially already authorized this site.
                    if test_key == good_key:
                        if request.user.authorizedclient_set.filter(
                                site=auth_callback.netloc):
                            # The user has authorized this site; Reset the
                            # current session expiry, add the key to the
                            # callback url, and redirect to it.
                            request.session.set_expiry(None)

                            q = urlparse.parse_qs(auth_callback.query)
                            q.update({'key': good_key})
                            auth_callback = auth_callback._replace(
                                query=urlencode(q))
                            return redirect(urlparse.urlunparse(auth_callback))
                        else:
                            # The user at one time authorized this site but it
                            # was revoked (potential future functionality?).
                            # Ask for authorization again.
                            return render_to_response('mysignon/sso_auth.html',
                                                      data,
                                                      RequestContext(request))
                    else:
                        # The key provided does not match the user's key; Log
                        # the user out. It may be a different user's key.
                        logout(request)
                else:
                    # No key was provided; Proceed to authorization normally.
                    return render_to_response('mysignon/sso_auth.html', data,
                                              RequestContext(request))
            else:
                # The user has no key; Create one.
                request.session['key'] = AuthorizedClient.create_key(
                    request.user)
                if test_key:
                    # A key was provided, but the current user did not have one
                    # until now. Log out the user.
                    logout(request)
                else:
                    # No key was provided; Proceed to authorization.
                    return render_to_response('mysignon/sso_auth.html', data,
                                              RequestContext(request))

        # Only anonymous users can reach this point. This is not inside an else
        # block so that it can catch users who were logged out above.
        login_form = CustomAuthForm(auto_id=True)
        login_form.fields.pop('remember_me')
        data['login_form'] = login_form
        return render_to_response('mysignon/sso_auth.html', data,
                                  RequestContext(request))

    else:
        # Form was posted.
        action = request.POST.get('action')
        if action == 'login':
            login_form = CustomAuthForm(data=request.POST, auto_id=False)
            login_form.fields.pop('remember_me')
            if login_form.is_valid():
                user = authenticate(
                    username=login_form.cleaned_data['username'],
                    password=login_form.cleaned_data['password'])
                login(request, user)
                request.session.set_expiry(None)
                # User was logged in. Fall through to code common to
                # preauthenticated users
            else:
                if request.is_ajax():
                    return HttpResponse(
                        json.dumps({'errors': login_form.errors.items()}))
                else:
                    data['login_form'] = login_form
                    data['auth_callback_short'] = auth_callback.netloc

                    return render_to_response('mysignon/sso_auth.html', data,
                                              RequestContext(request))

        # Ensure that an AuthorizedClient instance exists for the current user
        # and the site that is requesting authorization.
        request.user.authorizedclient_set.get_or_create(
            site=auth_callback.netloc)

        # Ensure that the current user has a key.
        if not request.session.get('key'):
            request.session['key'] = AuthorizedClient.create_key(request.user)

        # Add the user's key to the callback url and redirect to it.
        q = urlparse.parse_qs(auth_callback.query)
        q.update({'key': request.session.get('key')})
        auth_callback = auth_callback._replace(query=urlencode(q))
        auth_callback = urlparse.urlunparse(auth_callback)
        if request.is_ajax():

            return HttpResponse(json.dumps({'url': auth_callback}))
        else:
            return redirect(auth_callback)
Example #4
0
def sso_authorize(request):
    """
    Authorizes specific web sites to utilize an existing My.jobs account

    Required on HTTP GET:
    :auth_callback: GET parameter - Desired return url when authorization
        succeeds

    Required on HTTP POST:
    :auth_callback: POST parameter, copy of :auth_callback: GET parameter
    """
    # Common between GET and POST, callback is required.
    auth_callback = request.GET.get('auth_callback') or \
        request.POST.get('auth_callback')
    data = {'auth_callback': auth_callback}

    if auth_callback:
        auth_callback = unquote(auth_callback)
        auth_callback = urlparse.urlparse(auth_callback)
        if not auth_callback.netloc:
            # If the base url of the callback is not truthy, the url
            # must be malformed somehow
            raise Http404("mysignon.views.sso_authorize: bad callback")
    else:
        raise Http404("mysignon.views.sso_authorize: no callback")

    if request.method == 'GET':
        # Initial view after being redirected from an external site
        data['auth_callback_short'] = auth_callback.netloc

        if not request.user.is_anonymous():
            # Process logged in users first; Certain criteria may cause the
            # user to be logged out.
            good_key = request.session.get('key')
            test_key = request.GET.get('key')
            if good_key:
                # The current user already has a key available.
                if test_key:
                    # The remote site has provided a key; the user has
                    # potentially already authorized this site.
                    if test_key == good_key:
                        if request.user.authorizedclient_set.filter(
                                site=auth_callback.netloc):
                            # The user has authorized this site; Reset the
                            # current session expiry, add the key to the
                            # callback url, and redirect to it.
                            request.session.set_expiry(None)

                            q = urlparse.parse_qs(auth_callback.query)
                            q.update({'key': good_key})
                            auth_callback = auth_callback._replace(
                                query=urlencode(q))
                            return redirect(urlparse.urlunparse(auth_callback))
                        else:
                            # The user at one time authorized this site but it
                            # was revoked (potential future functionality?).
                            # Ask for authorization again.
                            return render_to_response('mysignon/sso_auth.html',
                                                      data,
                                                      RequestContext(request))
                    else:
                        # The key provided does not match the user's key; Log
                        # the user out. It may be a different user's key.
                        logout(request)
                else:
                    # No key was provided; Proceed to authorization normally.
                    return render_to_response('mysignon/sso_auth.html',
                                              data,
                                              RequestContext(request))
            else:
                # The user has no key; Create one.
                request.session['key'] = AuthorizedClient.create_key(
                    request.user)
                if test_key:
                    # A key was provided, but the current user did not have one
                    # until now. Log out the user.
                    logout(request)
                else:
                    # No key was provided; Proceed to authorization.
                    return render_to_response('mysignon/sso_auth.html',
                                              data,
                                              RequestContext(request))

        # Only anonymous users can reach this point. This is not inside an else
        # block so that it can catch users who were logged out above.
        login_form = CustomAuthForm(auto_id=True)
        login_form.fields.pop('remember_me')
        data['login_form'] = login_form
        return render_to_response('mysignon/sso_auth.html',
                                  data,
                                  RequestContext(request))

    else:
        # Form was posted.
        action = request.POST.get('action')
        if action == 'login':
            login_form = CustomAuthForm(data=request.POST, auto_id=False)
            login_form.fields.pop('remember_me')
            if login_form.is_valid():
                user = authenticate(
                    username=login_form.cleaned_data['username'],
                    password=login_form.cleaned_data['password'])
                login(request, user)
                request.session.set_expiry(None)
                # User was logged in. Fall through to code common to
                # preauthenticated users
            else:
                if request.is_ajax():
                    return HttpResponse(json.dumps(
                        {'errors': login_form.errors.items()}))
                else:
                    data['login_form'] = login_form
                    data['auth_callback_short'] = auth_callback.netloc

                    return render_to_response('mysignon/sso_auth.html', data,
                                              RequestContext(request))

        # Ensure that an AuthorizedClient instance exists for the current user
        # and the site that is requesting authorization.
        request.user.authorizedclient_set.get_or_create(site=auth_callback.netloc)

        # Ensure that the current user has a key.
        if not request.session.get('key'):
            request.session['key'] = AuthorizedClient.create_key(request.user)

        # Add the user's key to the callback url and redirect to it.
        q = urlparse.parse_qs(auth_callback.query)
        q.update({'key': request.session.get('key')})
        auth_callback = auth_callback._replace(query=urlencode(q))
        auth_callback = urlparse.urlunparse(auth_callback)
        if request.is_ajax():

            return HttpResponse(json.dumps({'url': auth_callback}))
        else:
            return redirect(auth_callback)