예제 #1
0
파일: auth.py 프로젝트: sivy/typepadapp
def synchronize(request):
    """Session synchronization.

    If a nonce is present, make sure it exists in the user's session and
    verify the signature. If successful, try to log the user in using the
    oauth token key specified in the query string.

    """
    from typepadapp.auth import authenticate, login
    from django.contrib.auth import logout

    # check query string, then session for next param. default to index.
    next = request.GET.get("callback_next", HOME_URL)
    nonce = request.GET.get("callback_nonce")

    if not nonce:
        return http.HttpResponse("No nonce.")
    else:
        callback_nonce = request.session.get("callback_nonce")
        if callback_nonce is not None:
            # Delete the nonce to prevent replay attacks.
            del request.session["callback_nonce"]

        session_sync_token = request.GET.get("session_sync_token")

        # log the user out / clear the existing session.
        logout(request)

        # Validate the request.
        if nonce != callback_nonce:
            # nonce's don't match, either a bug or someone's playing games
            return http.HttpResponseRedirect(next)

        oauth_request = oauth.OAuthRequest.from_request(
            request.method,
            request.build_absolute_uri(),
            parameters=dict(request.GET.items()),
            query_string=request.environ.get("QUERY_STRING", ""),
        )
        oauth_server = oauth.OAuthServer(StupidDataStore())
        oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1())
        try:
            consumer, gp_token, params = oauth_server.verify_request(oauth_request)
        except oauth.OAuthError, ex:
            # OAuth signature is invalid. Something's fishy. Don't log them in.
            return http.HttpResponse(ex.message, status=400)

        # The register URL needs to retain the 'next' querystring param so we
        # can redirect to the correct place once registeration is complete.
        register_url = parameterize_url(reverse("register"), {"next": next})

        if session_sync_token:
            # If a token was returned, create a session loggin the user
            # in with the new token. Otherwise we just log the user out.
            token = Token.get(session_sync_token)
            if token is None:
                # We lost the token somehow.
                if request.GET.get("signin", False):
                    # They clicked sign in, but we don't have the token
                    # so we redirect to the register auth flow so we're issued
                    # a new token.
                    return http.HttpResponseRedirect(register_url)
                else:
                    # In this case we store the lost token in the user's session. In future
                    # session sync requests this "lost" token will be used instead of the
                    # logged in users' token for the `current_token` param. That way we don't
                    # get stuck in a loop.
                    request.session["lost_session_sync_token"] = session_sync_token
                    return http.HttpResponseRedirect(next)
            client = OAuthClient(request.application)
            client.token = token

            # Everything's copasetic. Authorize and login user.
            authed_user = authenticate(oauth_client=client)
            login(request, authed_user)
            request.session["oauth_token"] = token
        else:
            if request.GET.get("signin", False):
                # If there's no token returned and the user clicked 'signin' then
                # they haven't auth'd this site to access their info. Send them
                # to register instead.
                return http.HttpResponseRedirect(register_url)

        return http.HttpResponseRedirect(next)