def step2_exchange(self, code=None, http=None, device_flow_info=None):
        """Exchanges a code for OAuth2Credentials.

        Args:
            code: string, a dict-like object, or None. For a non-device
                  flow, this is either the response code as a string, or a
                  dictionary of query parameters to the redirect_uri. For a
                  device flow, this should be None.
            http: httplib2.Http, optional http instance to use when fetching
                  credentials.
            device_flow_info: DeviceFlowInfo, return value from step1 in the
                              case of a device flow.

        Returns:
            An OAuth2Credentials object that can be used to authorize requests.

        Raises:
            FlowExchangeError: if a problem occurred exchanging the code for a
                               refresh_token.
            ValueError: if code and device_flow_info are both provided or both
                        missing.
        """
        if code is None and device_flow_info is None:
            raise ValueError('No code or device_flow_info provided.')
        if code is not None and device_flow_info is not None:
            raise ValueError('Cannot provide both code and device_flow_info.')

        if code is None:
            code = device_flow_info.device_code
        elif not isinstance(code, (six.string_types, six.binary_type)):
            if 'code' not in code:
                raise FlowExchangeError(code.get(
                    'error', 'No code was supplied in the query parameters.'))
            code = code['code']

        post_data = {
            'client_id': self.client_id,
            'code': code,
            'scope': self.scope,
        }
        if self.client_secret is not None:
            post_data['client_secret'] = self.client_secret
        if self._pkce:
            post_data['code_verifier'] = self.code_verifier
        if device_flow_info is not None:
            post_data['grant_type'] = 'http://oauth.net/grant_type/device/1.0'
        else:
            post_data['grant_type'] = 'authorization_code'
            post_data['redirect_uri'] = self.redirect_uri
        body = urllib.parse.urlencode(post_data)
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }
        if self.authorization_header is not None:
            headers['Authorization'] = self.authorization_header
        if self.user_agent is not None:
            headers['user-agent'] = self.user_agent

        if http is None:
            http = transport.get_http_object()

        resp, content = transport.request(
            http, self.token_uri, method='POST', body=body, headers=headers)
        d = _parse_exchange_token_response(content)
        if resp.status == http_client.OK and 'access_token' in d:
            access_token = d['access_token']
            refresh_token = d.get('refresh_token', None)
            if not refresh_token:
                logger.info(
                    'Received token response with no refresh_token. Consider '
                    "reauthenticating with prompt='consent'.")
            token_expiry = None
            if 'expires_in' in d:
                delta = datetime.timedelta(seconds=int(d['expires_in']))
                token_expiry = delta + _UTCNOW()

            extracted_id_token = None
            id_token_jwt = None
            if 'id_token' in d:
                extracted_id_token = _extract_id_token(d['id_token'])
                id_token_jwt = d['id_token']

            logger.info('Successfully retrieved access token')
            return OAuth2Credentials(
                access_token, self.client_id, self.client_secret,
                refresh_token, token_expiry, self.token_uri, self.user_agent,
                revoke_uri=self.revoke_uri, id_token=extracted_id_token,
                id_token_jwt=id_token_jwt, token_response=d, scopes=self.scope,
                token_info_uri=self.token_info_uri)
        else:
            logger.info('Failed to retrieve access token: %s', content)
            if 'error' in d:
                # you never know what those providers got to say
                error_msg = (str(d['error']) +
                             str(d.get('error_description', '')))
            else:
                error_msg = 'Invalid response: {0}.'.format(str(resp.status))
            raise FlowExchangeError(error_msg)
def step2_exchange(self, code=None, http=None, device_flow_info=None):
        """Exchanges a code for OAuth2Credentials.

        Args:
            code: string, a dict-like object, or None. For a non-device
                  flow, this is either the response code as a string, or a
                  dictionary of query parameters to the redirect_uri. For a
                  device flow, this should be None.
            http: httplib2.Http, optional http instance to use when fetching
                  credentials.
            device_flow_info: DeviceFlowInfo, return value from step1 in the
                              case of a device flow.

        Returns:
            An OAuth2Credentials object that can be used to authorize requests.

        Raises:
            FlowExchangeError: if a problem occurred exchanging the code for a
                               refresh_token.
            ValueError: if code and device_flow_info are both provided or both
                        missing.
        """
        if code is None and device_flow_info is None:
            raise ValueError('No code or device_flow_info provided.')
        if code is not None and device_flow_info is not None:
            raise ValueError('Cannot provide both code and device_flow_info.')

        if code is None:
            code = device_flow_info.device_code
        elif not isinstance(code, (six.string_types, six.binary_type)):
            if 'code' not in code:
                raise FlowExchangeError(code.get(
                    'error', 'No code was supplied in the query parameters.'))
            code = code['code']

        post_data = {
            'client_id': self.client_id,
            'code': code,
            'scope': self.scope,
        }
        if self.client_secret is not None:
            post_data['client_secret'] = self.client_secret
        if self._pkce:
            post_data['code_verifier'] = self.code_verifier
        if device_flow_info is not None:
            post_data['grant_type'] = 'http://oauth.net/grant_type/device/1.0'
        else:
            post_data['grant_type'] = 'authorization_code'
            post_data['redirect_uri'] = self.redirect_uri
        body = urllib.parse.urlencode(post_data)
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }
        if self.authorization_header is not None:
            headers['Authorization'] = self.authorization_header
        if self.user_agent is not None:
            headers['user-agent'] = self.user_agent

        if http is None:
            http = transport.get_http_object()

        resp, content = transport.request(
            http, self.token_uri, method='POST', body=body, headers=headers)
        d = _parse_exchange_token_response(content)
        if resp.status == http_client.OK and 'access_token' in d:
            access_token = d['access_token']
            refresh_token = d.get('refresh_token', None)
            if not refresh_token:
                logger.info(
                    'Received token response with no refresh_token. Consider '
                    "reauthenticating with prompt='consent'.")
            token_expiry = None
            if 'expires_in' in d:
                delta = datetime.timedelta(seconds=int(d['expires_in']))
                token_expiry = delta + _UTCNOW()

            extracted_id_token = None
            id_token_jwt = None
            if 'id_token' in d:
                extracted_id_token = _extract_id_token(d['id_token'])
                id_token_jwt = d['id_token']

            logger.info('Successfully retrieved access token')
            return OAuth2Credentials(
                access_token, self.client_id, self.client_secret,
                refresh_token, token_expiry, self.token_uri, self.user_agent,
                revoke_uri=self.revoke_uri, id_token=extracted_id_token,
                id_token_jwt=id_token_jwt, token_response=d, scopes=self.scope,
                token_info_uri=self.token_info_uri)
        else:
            logger.info('Failed to retrieve access token: %s', content)
            if 'error' in d:
                # you never know what those providers got to say
                error_msg = (str(d['error']) +
                             str(d.get('error_description', '')))
            else:
                error_msg = 'Invalid response: {0}.'.format(str(resp.status))
            raise FlowExchangeError(error_msg)
def step2_exchange ( self , code = None , http = None , device_flow_info = None ) : if code is None and device_flow_info is None : raise ValueError ( 'No code or device_flow_info provided.' ) if code is not None and device_flow_info is not None : raise ValueError ( 'Cannot provide both code and device_flow_info.' ) if code is None : code = device_flow_info . device_code elif not isinstance ( code , ( six . string_types , six . binary_type ) ) : if 'code' not in code : raise FlowExchangeError ( code . get ( 'error' , 'No code was supplied in the query parameters.' ) ) code = code [ 'code' ] post_data = { 'client_id' : self . client_id , 'code' : code , 'scope' : self . scope , } if self . client_secret is not None : post_data [ 'client_secret' ] = self . client_secret if self . _pkce : post_data [ 'code_verifier' ] = self . code_verifier if device_flow_info is not None : post_data [ 'grant_type' ] = 'http://oauth.net/grant_type/device/1.0' else : post_data [ 'grant_type' ] = 'authorization_code' post_data [ 'redirect_uri' ] = self . redirect_uri body = urllib . parse . urlencode ( post_data ) headers = { 'content-type' : 'application/x-www-form-urlencoded' , } if self . authorization_header is not None : headers [ 'Authorization' ] = self . authorization_header if self . user_agent is not None : headers [ 'user-agent' ] = self . user_agent if http is None : http = transport . get_http_object ( ) resp , content = transport . request ( http , self . token_uri , method = 'POST' , body = body , headers = headers ) d = _parse_exchange_token_response ( content ) if resp . status == http_client . OK and 'access_token' in d : access_token = d [ 'access_token' ] refresh_token = d . get ( 'refresh_token' , None ) if not refresh_token : logger . info ( 'Received token response with no refresh_token. Consider ' "reauthenticating with prompt='consent'." ) token_expiry = None if 'expires_in' in d : delta = datetime . timedelta ( seconds = int ( d [ 'expires_in' ] ) ) token_expiry = delta + _UTCNOW ( ) extracted_id_token = None id_token_jwt = None if 'id_token' in d : extracted_id_token = _extract_id_token ( d [ 'id_token' ] ) id_token_jwt = d [ 'id_token' ] logger . info ( 'Successfully retrieved access token' ) return OAuth2Credentials ( access_token , self . client_id , self . client_secret , refresh_token , token_expiry , self . token_uri , self . user_agent , revoke_uri = self . revoke_uri , id_token = extracted_id_token , id_token_jwt = id_token_jwt , token_response = d , scopes = self . scope , token_info_uri = self . token_info_uri ) else : logger . info ( 'Failed to retrieve access token: %s' , content ) if 'error' in d : # you never know what those providers got to say error_msg = ( str ( d [ 'error' ] ) + str ( d . get ( 'error_description' , '' ) ) ) else : error_msg = 'Invalid response: {0}.' . format ( str ( resp . status ) ) raise FlowExchangeError ( error_msg )
Exchanges a code for OAuth2Credentials.

        Args:
            code: string, a dict-like object, or None. For a non-device
                  flow, this is either the response code as a string, or a
                  dictionary of query parameters to the redirect_uri. For a
                  device flow, this should be None.
            http: httplib2.Http, optional http instance to use when fetching
                  credentials.
            device_flow_info: DeviceFlowInfo, return value from step1 in the
                              case of a device flow.

        Returns:
            An OAuth2Credentials object that can be used to authorize requests.

        Raises:
            FlowExchangeError: if a problem occurred exchanging the code for a
                               refresh_token.
            ValueError: if code and device_flow_info are both provided or both
                        missing.
Exchanges a code for OAuth2Credentials .