예제 #1
0
def _run_next_challenge(msg, http_request, access_token):
    """Get the next challenge from msg and run it.

    Args:
        msg: Reauth API response body (either from the initial request to
            https://reauth.googleapis.com/v2/sessions:start or from sending the
            previous challenge response to
            https://reauth.googleapis.com/v2/sessions/id:continue)
        http_request: callable to run http requests. Accepts uri, method, body
            and headers. Returns a tuple: (response, content)
        access_token: reauth access token

    Returns: rapt token.
    Raises:
        errors.ReauthError if reauth failed
    """
    for challenge in msg['challenges']:
        if challenge['status'] != 'READY':
            # Skip non-activated challneges.
            continue
        c = challenges.AVAILABLE_CHALLENGES.get(challenge['challengeType'],
                                                None)
        if not c:
            raise errors.ReauthFailError(
                'Unsupported challenge type {0}. Supported types: {1}'.format(
                    challenge['challengeType'],
                    ','.join(list(challenges.AVAILABLE_CHALLENGES.keys()))))
        if not c.is_locally_eligible:
            raise errors.ReauthFailError(
                'Challenge {0} is not locally eligible'.format(
                    challenge['challengeType']))
        client_input = c.obtain_challenge_input(challenge)
        if not client_input:
            return None
        return _reauth_client.send_challenge_result(http_request,
                                                    msg['sessionId'],
                                                    challenge['challengeId'],
                                                    client_input, access_token)
    return None
예제 #2
0
def _obtain_rapt(http_request, access_token, requested_scopes, rounds_num=5):
    """Given an http request method and reauth access token, get rapt token.

    Args:
        http_request: callable to run http requests. Accepts uri, method, body
            and headers. Returns a tuple: (response, content)
        access_token: reauth access token
        requested_scopes: scopes required by the client application
        rounds_num: max number of attempts to get a rapt after the next
            challenge, before failing the reauth. This defines total number of
            challenges + number of additional retries if the chalenge input
            wasn't accepted.

    Returns: rapt token.
    Raises:
        errors.ReauthError if reauth failed
    """
    msg = None

    for _ in range(0, rounds_num):

        if not msg:
            msg = _reauth_client.get_challenges(
                http_request, list(challenges.AVAILABLE_CHALLENGES.keys()),
                access_token, requested_scopes)

        if msg['status'] == _AUTHENTICATED:
            return msg['encodedProofOfReauthToken']

        if not (msg['status'] == _CHALLENGE_REQUIRED
                or msg['status'] == _CHALLENGE_PENDING):
            raise errors.ReauthAPIError('Challenge status {0}'.format(
                msg['status']))

        if not _helpers.is_interactive():
            raise errors.ReauthUnattendedError()

        msg = _run_next_challenge(msg, http_request, access_token)

    # If we got here it means we didn't get authenticated.
    raise errors.ReauthFailError()