def refresh_token(self,
                      token_url,
                      refresh_token=None,
                      body='',
                      auth=None,
                      timeout=None,
                      verify=True,
                      **kwargs):
        """Fetch a new access token using a refresh token.

        :param token_url: The token endpoint, must be HTTPS.
        :param refresh_token: The refresh_token to use.
        :param body: Optional application/x-www-form-urlencoded body to add the
                     include in the token request. Prefer kwargs over body.
        :param auth: An auth tuple or method as accepted by requests.
        :param timeout: Timeout of the request in seconds.
        :param verify: Verify SSL certificate.
        :param kwargs: Extra parameters to include in the token request.
        :return: A token dict
        """
        if not token_url:
            raise ValueError('No token endpoint set for auto_refresh.')

        if not is_secure_transport(token_url):
            raise InsecureTransportError()

        # Need to nullify token to prevent it from being added to the request
        refresh_token = refresh_token or self.token.get('refresh_token')
        self.token = {}

        log.debug('Adding auto refresh key word arguments %s.',
                  self.auto_refresh_kwargs)
        kwargs.update(self.auto_refresh_kwargs)
        body = self._client.prepare_refresh_body(body=body,
                                                 refresh_token=refresh_token,
                                                 scope=self.scope,
                                                 **kwargs)
        log.debug('Prepared refresh token request body %s', body)
        r = self.post(token_url,
                      data=dict(urldecode(body)),
                      auth=auth,
                      timeout=timeout,
                      verify=verify)
        log.debug('Request to refresh token completed with status %s.',
                  r.status_code)
        log.debug('Response headers were %s and content %s.', r.headers,
                  r.text)
        log.debug('Invoking %d token response hooks.',
                  len(self.compliance_hook['refresh_token_response']))
        for hook in self.compliance_hook['refresh_token_response']:
            log.debug('Invoking hook %s.', hook)
            r = hook(r)

        self.token = self._client.parse_request_body_response(r.text,
                                                              scope=self.scope)
        if not 'refresh_token' in self.token:
            log.debug('No new refresh token given. Re-using old.')
            self.token['refresh_token'] = refresh_token
        return self.token
Exemple #2
0
    def __call__(self, r):
        """Append an OAuth 2 token to the request.

        Note that currently HTTPS is required for all requests. There may be
        a token type that allows for plain HTTP in the future and then this
        should be updated to allow plain HTTP on a white list basis.
        """
        if not is_secure_transport(r.url):
            raise InsecureTransportError()
        r.url, r.headers, r.body = self._client.add_token(r.url,
                                                          http_method=r.method, body=r.body, headers=r.headers)
        return r
    def __call__(self, r):
        """Append an OAuth 2 token to the request.

        Note that currently HTTPS is required for all requests. There may be
        a token type that allows for plain HTTP in the future and then this
        should be updated to allow plain HTTP on a white list basis.
        """
        if not is_secure_transport(r.url):
            raise InsecureTransportError()
        r.url, r.headers, r.body = self._client.add_token(r.url,
                                                          http_method=r.method,
                                                          body=r.body,
                                                          headers=r.headers)
        return r
    def refresh_token(self, token_url, refresh_token=None, body='', auth=None,
                      timeout=None, verify=True, **kwargs):
        """Fetch a new access token using a refresh token.

        :param token_url: The token endpoint, must be HTTPS.
        :param refresh_token: The refresh_token to use.
        :param body: Optional application/x-www-form-urlencoded body to add the
                     include in the token request. Prefer kwargs over body.
        :param auth: An auth tuple or method as accepted by requests.
        :param timeout: Timeout of the request in seconds.
        :param verify: Verify SSL certificate.
        :param kwargs: Extra parameters to include in the token request.
        :return: A token dict
        """
        if not token_url:
            raise ValueError('No token endpoint set for auto_refresh.')

        if not is_secure_transport(token_url):
            raise InsecureTransportError()

        # Need to nullify token to prevent it from being added to the request
        refresh_token = refresh_token or self.token.get('refresh_token')
        self.token = {}

        log.debug('Adding auto refresh key word arguments %s.',
                  self.auto_refresh_kwargs)
        kwargs.update(self.auto_refresh_kwargs)
        body = self._client.prepare_refresh_body(body=body,
                                                 refresh_token=refresh_token, scope=self.scope, **kwargs)
        log.debug('Prepared refresh token request body %s', body)
        r = self.post(token_url, data=dict(urldecode(body)), auth=auth,
                      timeout=timeout, verify=verify)
        log.debug('Request to refresh token completed with status %s.',
                  r.status_code)
        log.debug('Response headers were %s and content %s.',
                  r.headers, r.text)
        log.debug('Invoking %d token response hooks.',
                  len(self.compliance_hook['refresh_token_response']))
        for hook in self.compliance_hook['refresh_token_response']:
            log.debug('Invoking hook %s.', hook)
            r = hook(r)

        self.token = self._client.parse_request_body_response(r.text, scope=self.scope)
        if not 'refresh_token' in self.token:
            log.debug('No new refresh token given. Re-using old.')
            self.token['refresh_token'] = refresh_token
        return self.token
    def request(self, method, url, data=None, headers=None, **kwargs):
        """Intercept all requests and add the OAuth 2 token if present."""
        if not is_secure_transport(url):
            raise InsecureTransportError()
        if self.token:
            log.debug('Invoking %d protected resource request hooks.',
                      len(self.compliance_hook['protected_request']))
            for hook in self.compliance_hook['protected_request']:
                log.debug('Invoking hook %s.', hook)
                url, headers, data = hook(url, headers, data)

            log.debug('Adding token %s to request.', self.token)
            try:
                url, headers, data = self._client.add_token(url,
                                                            http_method=method,
                                                            body=data,
                                                            headers=headers)
            # Attempt to retrieve and save new access token if expired
            except TokenExpiredError:
                if self.auto_refresh_url:
                    log.debug(
                        'Auto refresh is set, attempting to refresh at %s.',
                        self.auto_refresh_url)
                    token = self.refresh_token(self.auto_refresh_url)
                    if self.token_updater:
                        log.debug('Updating token to %s using %s.', token,
                                  self.token_updater)
                        self.token_updater(token)
                        url, headers, data = self._client.add_token(
                            url,
                            http_method=method,
                            body=data,
                            headers=headers)
                    else:
                        raise TokenUpdated(token)
                else:
                    raise

        log.debug('Requesting url %s using method %s.', url, method)
        log.debug('Supplying headers %s and data %s', headers, data)
        log.debug('Passing through key word arguments %s.', kwargs)
        return super(OAuth2Session, self).request(method,
                                                  url,
                                                  headers=headers,
                                                  data=data,
                                                  **kwargs)
    def request(self, method, url, data=None, headers=None, **kwargs):
        """Intercept all requests and add the OAuth 2 token if present."""
        if not is_secure_transport(url):
            raise InsecureTransportError()
        if self.token:
            log.debug('Invoking %d protected resource request hooks.',
                      len(self.compliance_hook['protected_request']))
            for hook in self.compliance_hook['protected_request']:
                log.debug('Invoking hook %s.', hook)
                url, headers, data = hook(url, headers, data)

            log.debug('Adding token %s to request.', self.token)
            try:
                url, headers, data = self._client.add_token(url,
                                                            http_method=method, body=data, headers=headers)
            # Attempt to retrieve and save new access token if expired
            except TokenExpiredError:
                if self.auto_refresh_url:
                    log.debug('Auto refresh is set, attempting to refresh at %s.',
                              self.auto_refresh_url)
                    token = self.refresh_token(self.auto_refresh_url)
                    if self.token_updater:
                        log.debug('Updating token to %s using %s.',
                                  token, self.token_updater)
                        self.token_updater(token)
                        url, headers, data = self._client.add_token(url,
                                                                    http_method=method, body=data, headers=headers)
                    else:
                        raise TokenUpdated(token)
                else:
                    raise

        log.debug('Requesting url %s using method %s.', url, method)
        log.debug('Supplying headers %s and data %s', headers, data)
        log.debug('Passing through key word arguments %s.', kwargs)
        return super(OAuth2Session, self).request(method, url,
                                                  headers=headers, data=data, **kwargs)
    def fetch_token(self, token_url, code=None, authorization_response=None,
                    body='', auth=None, username=None, password=None, method='POST',
                    timeout=None, headers=None, verify=True, **kwargs):
        """Generic method for fetching an access token from the token endpoint.

        If you are using the MobileApplicationClient you will want to use
        token_from_fragment instead of fetch_token.

        :param token_url: Token endpoint URL, must use HTTPS.
        :param code: Authorization code (used by WebApplicationClients).
        :param authorization_response: Authorization response URL, the callback
                                       URL of the request back to you. Used by
                                       WebApplicationClients instead of code.
        :param body: Optional application/x-www-form-urlencoded body to add the
                     include in the token request. Prefer kwargs over body.
        :param auth: An auth tuple or method as accepted by requests.
        :param username: Username used by LegacyApplicationClients.
        :param password: Password used by LegacyApplicationClients.
        :param method: The HTTP method used to make the request. Defaults
                       to POST, but may also be GET. Other methods should
                       be added as needed.
        :param headers: Dict to default request headers with.
        :param timeout: Timeout of the request in seconds.
        :param verify: Verify SSL certificate.
        :param kwargs: Extra parameters to include in the token request.
        :return: A token dict
        """
        if not is_secure_transport(token_url):
            raise InsecureTransportError()

        if not code and authorization_response:
            self._client.parse_request_uri_response(authorization_response,
                                                    state=self._state)
            code = self._client.code
        elif not code and isinstance(self._client, WebApplicationClient):
            code = self._client.code
            if not code:
                raise ValueError('Please supply either code or '
                                 'authorization_code parameters.')

        body = self._client.prepare_request_body(code=code, body=body,
                                                 redirect_uri=self.redirect_uri, username=username,
                                                 password=password, **kwargs)

        headers = headers or {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        }
        if method.upper() == 'POST':
            r = self.post(token_url, data=dict(urldecode(body)),
                          timeout=timeout, headers=headers, auth=auth,
                          verify=verify)
            log.debug('Prepared fetch token request body %s', body)
        elif method.upper() == 'GET':
            # if method is not 'POST', switch body to querystring and GET
            r = self.get(token_url, params=dict(urldecode(body)),
                         timeout=timeout, headers=headers, auth=auth,
                         verify=verify)
            log.debug('Prepared fetch token request querystring %s', body)
        else:
            raise ValueError('The method kwarg must be POST or GET.')

        log.debug('Request to fetch token completed with status %s.',
                  r.status_code)
        log.debug('Request headers were %s', r.request.headers)
        log.debug('Request body was %s', r.request.body)
        log.debug('Response headers were %s and content %s.',
                  r.headers, r.text)
        log.debug('Invoking %d token response hooks.',
                  len(self.compliance_hook['access_token_response']))
        for hook in self.compliance_hook['access_token_response']:
            log.debug('Invoking hook %s.', hook)
            r = hook(r)

        self._client.parse_request_body_response(r.text, scope=self.scope)
        self.token = self._client.token
        log.debug('Obtained token %s.', self.token)
        return self.token
    def fetch_token(self,
                    token_url,
                    code=None,
                    authorization_response=None,
                    body='',
                    auth=None,
                    username=None,
                    password=None,
                    method='POST',
                    timeout=None,
                    headers=None,
                    verify=True,
                    **kwargs):
        """Generic method for fetching an access token from the token endpoint.

        If you are using the MobileApplicationClient you will want to use
        token_from_fragment instead of fetch_token.

        :param token_url: Token endpoint URL, must use HTTPS.
        :param code: Authorization code (used by WebApplicationClients).
        :param authorization_response: Authorization response URL, the callback
                                       URL of the request back to you. Used by
                                       WebApplicationClients instead of code.
        :param body: Optional application/x-www-form-urlencoded body to add the
                     include in the token request. Prefer kwargs over body.
        :param auth: An auth tuple or method as accepted by requests.
        :param username: Username used by LegacyApplicationClients.
        :param password: Password used by LegacyApplicationClients.
        :param method: The HTTP method used to make the request. Defaults
                       to POST, but may also be GET. Other methods should
                       be added as needed.
        :param headers: Dict to default request headers with.
        :param timeout: Timeout of the request in seconds.
        :param verify: Verify SSL certificate.
        :param kwargs: Extra parameters to include in the token request.
        :return: A token dict
        """
        if not is_secure_transport(token_url):
            raise InsecureTransportError()

        if not code and authorization_response:
            self._client.parse_request_uri_response(authorization_response,
                                                    state=self._state)
            code = self._client.code
        elif not code and isinstance(self._client, WebApplicationClient):
            code = self._client.code
            if not code:
                raise ValueError('Please supply either code or '
                                 'authorization_code parameters.')

        body = self._client.prepare_request_body(
            code=code,
            body=body,
            redirect_uri=self.redirect_uri,
            username=username,
            password=password,
            **kwargs)

        headers = headers or {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
        }
        if method.upper() == 'POST':
            r = self.post(token_url,
                          data=dict(urldecode(body)),
                          timeout=timeout,
                          headers=headers,
                          auth=auth,
                          verify=verify)
            log.debug('Prepared fetch token request body %s', body)
        elif method.upper() == 'GET':
            # if method is not 'POST', switch body to querystring and GET
            r = self.get(token_url,
                         params=dict(urldecode(body)),
                         timeout=timeout,
                         headers=headers,
                         auth=auth,
                         verify=verify)
            log.debug('Prepared fetch token request querystring %s', body)
        else:
            raise ValueError('The method kwarg must be POST or GET.')

        log.debug('Request to fetch token completed with status %s.',
                  r.status_code)
        log.debug('Request headers were %s', r.request.headers)
        log.debug('Request body was %s', r.request.body)
        log.debug('Response headers were %s and content %s.', r.headers,
                  r.text)
        log.debug('Invoking %d token response hooks.',
                  len(self.compliance_hook['access_token_response']))
        for hook in self.compliance_hook['access_token_response']:
            log.debug('Invoking hook %s.', hook)
            r = hook(r)

        self._client.parse_request_body_response(r.text, scope=self.scope)
        self.token = self._client.token
        log.debug('Obtained token %s.', self.token)
        return self.token