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
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()