예제 #1
0
def verify_and_cache_oauth_or_cookie(request):
    """ For a given request, try to oauth-verify or cookie-verify it.

    If the request has a valid oauth token, we store all the auth
    info in a per-request global (for easy access) and return.

    If the request does not have a valid oauth token, but has a valid
    http cookie *and* a valid xsrf token, return.

    Otherwise -- including the cases where there is an oauth token or
    cookie but they're not valid, raise an OAuthError of one form or
    another.

    This function is designed to be idempotent: it's safe (and fast)
    to call multiple times on the same request.  It caches enough
    per-request information to avoid repeating expensive work.

    Arguments:
       request: A 'global' flask var holding the current active request.

    Raises:
       OAuthError: are not able to authenticate the current user.
         (Note we give OAuthError even when we're failing the
         cookie-based request, which is a bit of abuse of terminology
         since there's no oauth involved in that step.)
    """
    if hasattr(flask.g, "oauth_map"):
        # Already called this routine and succeeded, so no need to call again.
        return

    # is_valid_request() verifies this request has something in it
    # that looks like an oauth token.
    if is_valid_request(request):
        consumer, token, parameters = validate_token(request)
        if (not consumer) or (not token):
            raise OAuthError("Not valid consumer or token")

        # Store the OAuthMap containing all auth info in the request
        # global for easy access during the rest of this request.
        # We do this now because current_req_has_auth_credentials()
        # accesses oauth_map.
        flask.g.oauth_map = OAuthMap.get_from_access_token(token.key_)

        if not util.current_req_has_auth_credentials():
            # If our OAuth provider thinks you're logged in but the
            # identity providers we consume (Google/Facebook)
            # disagree, we act as if our token is no longer valid.
            del flask.g.oauth_map
            raise NotLoggedInError("verifying oauth token")

        # (We can do all the other global-setting after
        #  current_req_has_auth_credentials.)
        # Store enough information from the consumer token that we can
        # do anointed checks.
        # TODO(csilvers): is it better to just store all of
        # 'consumer'? Seems too big given we just need to cache this
        # one piece of information right now.
        flask.g.is_anointed = consumer.anointed

    elif util.allow_cookie_based_auth():
        # TODO(csilvers): simplify; this duplicates a lot of calls
        # (current_req_has_auth_credentials calls allow_cookie_based_auth too).
        # Would suffice to call util._get_current_user_id_from_cookies_unsafe()
        # and maybe auth_util.current_oauth_map_from_session_unsafe() as well.
        if not util.current_req_has_auth_credentials():
            raise NotLoggedInError("verifying cookie values")

    else:
        raise NotLoggedInError("looking at oauth headers and cookies")
예제 #2
0
def verify_and_cache_oauth_or_cookie(request):
    """ For a given request, try to oauth-verify or cookie-verify it.

    If the request has a valid oauth token, we store all the auth
    info in a per-request global (for easy access) and return.

    If the request does not have a valid oauth token, but has a valid
    http cookie *and* a valid xsrf token, return.

    Otherwise -- including the cases where there is an oauth token or
    cookie but they're not valid, raise an OAuthError of one form or
    another.

    This function is designed to be idempotent: it's safe (and fast)
    to call multiple times on the same request.  It caches enough
    per-request information to avoid repeating expensive work.

    Arguments:
       request: A 'global' flask var holding the current active request.

    Raises:
       OAuthError: are not able to authenticate the current user.
         (Note we give OAuthError even when we're failing the
         cookie-based request, which is a bit of abuse of terminology
         since there's no oauth involved in that step.)
    """
    if hasattr(flask.g, "oauth_map"):
        # Already called this routine and succeeded, so no need to call again.
        return

    # is_valid_request() verifies this request has something in it
    # that looks like an oauth token.
    if is_valid_request(request):
        consumer, token, parameters = validate_token(request)
        if (not consumer) or (not token):
            raise OAuthError("Not valid consumer or token")

        # Store the OAuthMap containing all auth info in the request
        # global for easy access during the rest of this request.
        # We do this now because current_req_has_auth_credentials()
        # accesses oauth_map.
        flask.g.oauth_map = OAuthMap.get_from_access_token(token.key_)

        if not util.current_req_has_auth_credentials():
            # If our OAuth provider thinks you're logged in but the
            # identity providers we consume (Google/Facebook)
            # disagree, we act as if our token is no longer valid.
            del flask.g.oauth_map
            raise NotLoggedInError("verifying oauth token")

        # Child users cannot authenticate against our API via oauth unless the
        # oauth consumer is anointed by us. This stops children from approving
        # third party app data access.
        if not consumer.anointed and user_util.is_current_user_child():
            del flask.g.oauth_map
            raise NotLoggedInError("under-13 accounts are denied API access")

        # (We can do all the other global-setting after
        #  current_req_has_auth_credentials.)
        # Store enough information from the consumer token that we can
        # do anointed checks.
        # TODO(csilvers): is it better to just store all of
        # 'consumer'? Seems too big given we just need to cache this
        # one piece of information right now.
        flask.g.is_anointed = consumer.anointed

    elif util.allow_cookie_based_auth():
        # TODO(csilvers): simplify; this duplicates a lot of calls
        # (current_req_has_auth_credentials calls allow_cookie_based_auth too).
        # Would suffice to call util._get_current_user_id_from_cookies_unsafe()
        # and maybe auth_util.current_oauth_map_from_session_unsafe() as well.
        if not util.current_req_has_auth_credentials():
            raise NotLoggedInError("verifying cookie values")

    else:
        raise NotLoggedInError("looking at oauth headers and cookies")