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

Usage Question: ROPCAccessToken usage causes assert req["grant_type"] == "authorization_code" assert error #615

Closed
BogdanOptibrium opened this issue Feb 20, 2019 · 11 comments
Assignees
Labels

Comments

@BogdanOptibrium
Copy link

Hi, I'm trying to get the Resource Ownger Password Credentials Grant working and i'm getting an error. When i'm trying to run the following code

    keys = [{ 
            'type': 'RSA',
            'key':'../OP/keys/key.pem',
            'use': ['enc', 'sig']
    }]

    _, keyjar, _ = build_keyjar(keys)
    global client
    client = Client(verify_ssl=False, keyjar=keyjar, client_authn_method=CLIENT_AUTHN_METHOD)
    issuer_url = client.wf.discovery_query('localhost')
    provider_info = client.provider_config(issuer_url)

    reg_info = {'application_type': 'native',
                'application_name': 'Example RP',
                'redirect_uris': ['http://127.0.0.1:5001/HybFlow'],
                }

    client_reg = client.register(provider_info["registration_endpoint"], **reg_info)
    client.store_registration_info(client_reg)

    request_args = {
        'grant_type': 'password',
        'client_id': client.client_id,
        'username': 'diana',
        'password': 'krall'
    }

   
    client.do_access_token_request(request=ROPCAccessTokenRequest,request_args=request_args)                    
    return

I get the following assert error. Can anyone please guide me on what i am doing wrong in trying to get a token using the Password Grant Flow?

Traceback (most recent call last): File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 2309, in __call__ return self.wsgi_app(environ, start_response) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 2295, in wsgi_app response = self.handle_exception(e) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 269, in error_router return original_handler(e) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1741, in handle_exception reraise(exc_type, exc_value, tb) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\_compat.py", line 34, in reraise raise value.with_traceback(tb) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 269, in error_router return original_handler(e) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\_compat.py", line 34, in reraise raise value.with_traceback(tb) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1799, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 458, in wrapper resp = resource(*args, **kwargs) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\views.py", line 88, in view return self.dispatch_request(*args, **kwargs) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 573, in dispatch_request resp = meth(*args, **kwargs) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\src\OP.py", line 102, in post authn=request.headers.environ['HTTP_AUTHORIZATION'] File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\oic\oic\provider.py", line 1115, in token_endpoint return self._access_token_endpoint(req, **kwargs) File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\oic\oic\provider.py", line 964, in _access_token_endpoint assert req["grant_type"] == "authorization_code" AssertionError

@schlenk
Copy link
Collaborator

schlenk commented Feb 20, 2019

It should probably be a NotImplementedError, as that is what it checks.
The ResourceOwnerPasswordCredentials Grant style is not supported in that code.

If you used the oic.extensions.provider in there, it should work, as that has the support code for password grants.

https://github.com/OpenIDC/pyoidc/blob/master/src/oic/extension/provider.py

@BogdanOptibrium
Copy link
Author

BogdanOptibrium commented Feb 21, 2019

Thank you very much for your answer, that helped me towards the right path. I have a few folowup questions:

  1. Is it possible to get the id_token using the ROPC Grant?

  2. Is it possible to define my own authorization function (simmilar to the simple_op example)? I'd be grateful for any pointers towards this.

  3. In the provider the password_grant_type function thorws an exception trying to access an inexistent member "access_token" in the _info variable (code snippet below). Could you please advise me towards what i'm doing wrong?

     keys = [{
     "type": "RSA",
     "key": "../OP/keys/key.pem",
     "use": ["enc", "sig"]
     }]
    
     _, keyjar, _ = build_keyjar(keys)
     global client
     client = Client(verify_ssl=False, keyjar=keyjar, client_authn_method=CLIENT_AUTHN_METHOD)
     issuer_url = 'https://localhost'
     provider_info = client.provider_config(issuer_url)
    
     reg_info = {'application_type': 'web',
                 'application_name': 'Example RP',
                 'redirect_uris': ['https://127.0.0.1:5001/HybFlow'],
                 'grant_type': ['password'],
                 }
    
     client_reg = client.register(provider_info["registration_endpoint"], **reg_info)
     client.store_registration_info(client_reg)
    
     request_args = {
         'grant_type': 'password',
         'client_id': client.client_id,
         'response_type': 'token id_token',
         'scope': ['openid', 'profile'],
         'state': state,
         'username': 'diana',
         'password': 'krall'
     }
    
     client.do_access_token_request(request=ROPCAccessTokenRequest,
                                          request_args=request_args,
                                          endpoint=client.token_endpoint,
                                          )
     return
    

Here is the function where it checks for the "access_token" member (oic.extension.provider)

def password_grant_type(self, areq):

    _at = self.token_handler.get_access_token(areq['client_id'],
                                              scope=areq['scope'],
                                              grant_type='password')
    _info = self.token_handler.token_factory.get_info(_at)
    try:
        _rt = self.token_handler.get_refresh_token(
            self.baseurl, _info['access_token'], 'password')
    except NotAllowed:
    # except:
        atr = self.do_access_token_response(_at, _info, areq['state'])
    else:
        atr = self.do_access_token_response(_at, _info, areq['state'], _rt)

    return Response(atr.to_json(), content="application/json")

And the call stack:

Traceback (most recent call last):
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 269, in error_router
    return original_handler(e)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 269, in error_router
    return original_handler(e)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 458, in wrapper
    resp = resource(*args, **kwargs)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask\views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\flask_restful\__init__.py", line 573, in dispatch_request
    resp = meth(*args, **kwargs)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\src\OP.py", line 104, in post
    class PyDBCommandThread(PyDBDaemonThread):
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\oic\extension\provider.py", line 771, in token_endpoint
    return self.password_grant_type(areq)
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\oic\extension\provider.py", line 728, in password_grant_type
    self.baseurl, _info['access_token'], 'password')
  File "C:\Users\bogdan\Projects\Learning\Python\oidc\OP\venv\lib\site-packages\oic\oauth2\message.py", line 764, in __getitem__
    return self._dict[item]
KeyError: 'access_token'

Thank you in advance for your help

@tpazderka
Copy link
Collaborator

Ad 1) As far as I can tell, it should be possible. Whether it is in fact implemented properly is another question :) Bug reports and/or pull requests are welcomed!
Ad 2) You can probably have a look here and extend/modify the one that suits you the best.
Ad 3) Can you please dump the created request? (areq.to_dict() inside the password_grant_type method)?

@BogdanOptibrium
Copy link
Author

Thank you for the answers.

Here is the dump of the areq taken from inside the password_grant_type method:

{
'grant_type': 'password',
'client_id': 'GIsQklgLloso',
'response_type': 'token id_token',
'scope': 'openid profile',
'state': 'kfU5OpVAtZiMu6a9',
'username': 'diana',
'password': 'krall'
}

Thank you for your help

@tpazderka
Copy link
Collaborator

Looks OK. How about _at.to_dict() and _info.to_dict() in the same function?

@BogdanOptibrium
Copy link
Author

Sure, here are the contents of those variables:

_at="eyJhbGciOiJSUzI1NiIsImtpZCI6InRwN2dJUGwtTFlkekRNbXRpQkNnbWcxVHBLWGVJUFRScU9Edmp1QjFzb3cifQ.eyJpc3MiOiAiaHR0cHM6Ly9sb2NhbGhvc3QvIiwgImlhdCI6IDE1NTEwODI3NTcsICJleHAiOiAxNTUxMDgzMzU3LCAia2lkIjogInRwN2dJUGwtTFlkekRNbXRpQkNnbWcxVHBLWGVJUFRScU9Edmp1QjFzb3ciLCAianRpIjogIlQtN2EwMzc1ZTQwMGUxNDZhZGIyMDNlYzY4ZGRmNTBmYWMiLCAic2NvcGUiOiAib3BlbmlkIHByb2ZpbGUiLCAiYXVkIjogWyJteE9WMVQ1RFFYRFIiXSwgImF6cCI6ICJteE9WMVQ1RFFYRFIifQ.xVLEdsyWcjJUks3y5l_eUItUAK08QJfMSWCZB_gYiaUbgWifnrc0RIvH8BPaKEbxoYMR3GbJzbwOnA-M5KHHhwhI3ivtJ787ZBBRR5Fq3BCa6Lmlqh2-nTpDGgJFXMy3BVx7_EoA2wTXayOTnUVW_PjWVZqvQrpo787_fQyasx7oUKzfkU47JKvbZH7K-cuh6ni5Wfv9GL581PXqY96fuPlzAQYG-4YCPiwKvgjsc0OKCoW-9LPvD45mkgsF8vZqddtLJTRwbqpuEDXqb1H1J6s0D0AOBJipi0Tthyl7WZdknLJyNJ8azzhFFLUwDJWm1fe7GPsvt2d4iAt5p28Hqw"

_info = {
"iss": "https://localhost/",
"iat": 1551082757,
"exp": 1551083357,
"kid": "tp7gIPl-LYdzDMmtiBCgmg1TpKXeIPTRqODvjuB1sow",
"jti": "T-7a0375e400e146adb203ec68ddf50fac",
"scope": "openid profile",
"aud": [
"mxOV1T5DQXDR"
],
"azp": "mxOV1T5DQXDR"
}

The _info does not have a "access_token" member causing an exception to be thrown, excepion of type KeyError which is not caught.

@tpazderka
Copy link
Collaborator

Hm, looking at the code at the token, the access_code is not inserted there.

This looks like a miss in implementation unless I am missing something.

@rohe Can you please chime in and confirm/deny the bug?

@rohe
Copy link
Contributor

rohe commented Feb 27, 2019

I haven't touched the extension library in ages. Must be at least 4-5 years.
As I don't think anyone else has kept it updated I would be very surprised if it wasn't seriously out of synch with the base.
Also, I used the extension library for experimental stuff so no rigorous testing.

Yes, I would call it a bug.

@tpazderka
Copy link
Collaborator

@rohe Thanks!

I will try to have a look and get them in sync.

@tpazderka
Copy link
Collaborator

The extension part looks quite a lot of out of sync and it will take come effort to bring them back together. I will probably try to clean up the duplicates first and then focus on writing tests and fixing the implementation.

@tpazderka
Copy link
Collaborator

I have attempted a simple fix in fix-ropc branch, could you please try if it works for you?

tpazderka added a commit that referenced this issue Mar 31, 2019
@tpazderka tpazderka mentioned this issue Mar 31, 2019
2 tasks
tpazderka added a commit that referenced this issue Apr 2, 2019
andrewkrug pushed a commit to mozilla-iam/pyoidc that referenced this issue Jun 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants