Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

do_access_token_request throws a requests.exceptions.Timeout #767

Open
Robinyo opened this issue Jan 13, 2021 · 7 comments
Open

do_access_token_request throws a requests.exceptions.Timeout #767

Robinyo opened this issue Jan 13, 2021 · 7 comments

Comments

@Robinyo
Copy link

Robinyo commented Jan 13, 2021

I have a Relying Party that receives a requests.exceptions.Timeout when it invokes do_access_token_request:

   2021-01-13T10:42:05.37+1100 [APP/PROC/WEB/0] ERR ERROR:oic.oauth2.base:http_request failed: HTTPSConnectionPool(host='onb.auth.identity.gov.au', port=443): Read timed out. (read timeout=5),
     url: https://onb.auth.identity.gov.au/sso/sps/oauth/oauth20/token,
     htargs: {'allow_redirects': False,
              'cert': None, 
              'verify': True, 
              'timeout': 5, 
              'data': 'grant_type=authorization_code&
                &code=9kWBBMTYOw9KU8dGmQrBQd8ESe3obM&
                redirect_uri=https<EDITED>&
                state=Z0NNMo9dJvEOUag3SaquOpCQI8gjWGe2&
                client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6Im5HdzdHSk12cGJ2WnpOdFg1YnlkMkJTcW5ZYTFsSV83MFE2Q3hycGtJYXMifQ.eyJpc3MiOiAiZ292cGFzcy1ycC1kdGEtdGVzdC1mNmU5ZDg4Zi1iODMyIiwgInN1YiI6ICJnb3ZwYXNzLXJwLWR0YS10ZXN0LWY2ZTlkODhmLWI4MzIiLCAiYXVkIjogWyJodHRwczovL29uYi5hdXRoLmlkZW50aXR5Lmdvdi5hdS9zc28vc3BzL29hdXRoL29hdXRoMjAvdG9rZW4iXSwgImp0aSI6ICJCUVZ3clhwUVFjMEl3WkI5N0hWZDBLTlhHRUlNOGNvRCIsICJleHAiOiAxNjEwNDk1MjIwLCAiaWF0IjogMTYxMDQ5NDkyMH0.z8t9nqAx5yliAou7PL2cwq7kU0Zq8PmRxTWK0EAYVahKKQmIElAtlwtDJF3BYE9PqqxzTv2LfuA-6lVYwAur7WZFhU9Kg6gYnelluveCKijqdJreTUnTnYM0q_7Bp8rV6fu5SifJBLjipuho4cE5ZSc6BsJ8iTFCV23RjGn9MRa3tUTPW3Fwi3rVfLnCUX4FyOB93ARd-NRtayHY-ADRDk-XPFbUpPNs-dn49qermCGtRYZiQdpXmn4ghqnAEiKgTuSLXgLgJ801Ftj_4hp1c79ZSHE8hjR97w8suCqlzrwA-Pnd6B2eZ4SxUao-6ojheMP8v0S9JbkS88eRz26LYw&
                client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer', 
                'headers': {'Content-Type': 'application/x-www-form-urlencoded'}}, method: POST

Is it possible to set the timeout?

import builtins
import json
import logging
import os

import requests
from flask import Blueprint, jsonify, render_template, request
from oic.oic.message import RegistrationResponse, AuthorizationResponse, ProviderConfigurationResponse
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic.utils.keyio import build_keyjar
from oic.utils.rp.__init__ import Client

di_api = Blueprint('di_api', __name__)

...

@di_api.route('/success', methods=["GET"])
def digital_identity_success():

  response = str(request.query_string)
  response = response[2:-1]

  auth_resp = di_client.parse_response(AuthorizationResponse, info=response, sformat="urlencoded")

  args = {
    "grant_type": "authorization_code",
    "code": auth_resp["code"],
    "redirect_uri": di_client.registration_response["redirect_uris"][0]
  }

  error = False

  try:

    response = di_client.do_access_token_request(
      state=auth_resp["state"],
      request_args=args,
      authn_method="private_key_jwt",
      lifetime=300
    )

    _token = response["access_token"]
    _id_token = response.get("id_token")

  except requests.exceptions.Timeout:
    error = True
    _id_token = "Exception: requests.exceptions.Timeout"

  except:
    error = True
    _id_token = "Exception: ..."

  return render_template("success.html", error=error, id_token=_id_token)

@tpazderka
Copy link
Collaborator

timeout is kwarg/setting to the base class, so you should be able to use it.

kwarg: https://github.com/OpenIDC/pyoidc/blob/master/src/oic/oauth2/base.py#L29
setting object: https://github.com/OpenIDC/pyoidc/blob/master/src/oic/oauth2/base.py#L30

@Robinyo
Copy link
Author

Robinyo commented Jan 14, 2021

What did you have in mind?

https://github.com/OpenIDC/pyoidc/blob/master/src/oic/utils/rp/__init__.py#L32

class Client(oic.Client):

https://github.com/OpenIDC/pyoidc/blob/master/src/oic/oic/__init__.py#L327

class Client(oauth2.Client):

https://github.com/OpenIDC/pyoidc/blob/master/src/oic/oauth2/__init__.py#L169

class Client(PBase):

Invoking the PBase constructor via super()?

from oic.utils.rp.__init__ import Client

class MyClient(Client):
  def __init__(self):
    print('Initialising: class MyClient')
    PBase.super()__init__(...)

@tpazderka
Copy link
Collaborator

It looks like not Clients take the argument...

I am not sure why are you using the Client from rp.utils, but you could perhaps use the oic.Client which takes Settings and the timeout can be configured there.

The other option is to redefine the __init__ method and pass the timeout yourself.

The switch to using Settings classes is work in progress and not everything can be configured.

@Robinyo
Copy link
Author

Robinyo commented Jan 14, 2021

I am not sure why are you using the Client from rp.utils, but you could perhaps use the oic.Client which takes Settings and the timeout can be configured there.

It's some sample code that was written by someone else that I have been asked to look at (i.e., it was working but it's not working now).

The code is using oic==1.2.0

According to the change log the 'Settings' functionality has not yet been released:

Unreleased
Changed
#763 Drop python 3.5 support
Added
#739 Better error message for providers which return HTTP Error 405 on userinfo
#723 Add settings class to handle settings related to Client and Server

The oic.Client doesn't accept a timeout:

https://github.com/OpenIDC/pyoidc/blob/1.2.x/src/oic/oic/__init__.py#L323

    def __init__(
        self,
        client_id=None,
        client_prefs=None,
        client_authn_method=None,
        keyjar=None,
        verify_ssl=True,
        config=None,
        client_cert=None,
        requests_dir="requests",
        message_factory: Type[MessageFactory] = OIDCMessageFactory,
    ):

        oauth2.Client.__init__(
            self,
            client_id,
            client_authn_method=client_authn_method,
            keyjar=keyjar,
            verify_ssl=verify_ssl,
            config=config,
            client_cert=client_cert,
            message_factory=message_factory,
        )

  ...

@ioparaskev
Copy link

wouldn't it also make some sense to raise a custom Timeout exception instead of having the requests exception bubble up? Currently only status codes != 200 raise a custom exception (CommunicationError)

@Robinyo
Copy link
Author

Robinyo commented Jan 18, 2021

Ok, so what I did was:

  • create a fork of pyoidc
  • changed the default timeout value to 30 (from 5)
  • updated my requirements.txt file to use the forked version of pyoidc
# oic==1.2.0
git+git://github.com/Robinyo/pyoidc@master#egg=oic

Now I am receiving a:

   2021-01-18T11:34:55.49+1100 [APP/PROC/WEB/0] ERR ERROR:oic.oauth2:Missing or faulty response

I'll do some more investigation ...

@tpazderka
Copy link
Collaborator

In that case, you will need to overload the __init__ and assign the timeout manually yourself. Once the settings are done, it should be possible to set it via that.

Yes, various errors from library should be catched and rethrown as our own errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants