def refresh_token_grant_type(self, areq): at = self.token_handler.refresh_access_token(self.baseurl, areq['access_token'], 'refresh_token') atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **at)) return Response(atr.to_json(), content="application/json")
def code_grant_type(self, areq): # assert that the code is valid try: _info = self.sdb[areq["code"]] except KeyError: err = TokenErrorResponse(error="invalid_grant", error_description="Unknown access grant") return Response(err.to_json(), content="application/json", status="401 Unauthorized") authzreq = json.loads(_info['authzreq']) if 'code_verifier' in areq: try: _method = authzreq['code_challenge_method'] except KeyError: _method = 'S256' resp = self.verify_code_challenge(areq['code_verifier'], authzreq['code_challenge'], _method) if resp: return resp if 'state' in areq: if self.sdb[areq['code']]['state'] != areq['state']: err = TokenErrorResponse(error="unauthorized_client") return Unauthorized(err.to_json(), content="application/json") resp = self.token_scope_check(areq, _info) if resp: return resp # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _info: assert areq["redirect_uri"] == _info["redirect_uri"] issue_refresh = False if 'scope' in authzreq and 'offline_access' in authzreq['scope']: if authzreq['response_type'] == 'code': issue_refresh = True try: _tinfo = self.sdb.upgrade_to_token(areq["code"], issue_refresh=issue_refresh) except AccessCodeUsed: err = TokenErrorResponse(error="invalid_grant", error_description="Access grant used") return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("_tinfo: %s" % _tinfo) atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo)) logger.debug("AccessTokenResponse: %s" % atr) return Response(atr.to_json(), content="application/json")
def code_grant_type(self, areq): # assert that the code is valid try: _info = self.sdb[areq["code"]] except KeyError: err = TokenErrorResponse(error="invalid_grant", error_description="Unknown access grant") return Response(err.to_json(), content="application/json", status="401 Unauthorized") authzreq = json.loads(_info['authzreq']) if 'code_verifier' in areq: try: _method = authzreq['code_challenge_method'] except KeyError: _method = 'S256' resp = self.verify_code_challenge(areq['code_verifier'], authzreq['code_challenge'], _method) if resp: return resp if 'state' in areq: if self.sdb[areq['code']]['state'] != areq['state']: logger.error('State value mismatch') err = TokenErrorResponse(error="unauthorized_client") return Unauthorized(err.to_json(), content="application/json") resp = self.token_scope_check(areq, _info) if resp: return resp # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _info: assert areq["redirect_uri"] == _info["redirect_uri"] issue_refresh = False if 'scope' in authzreq and 'offline_access' in authzreq['scope']: if authzreq['response_type'] == 'code': issue_refresh = True try: _tinfo = self.sdb.upgrade_to_token(areq["code"], issue_refresh=issue_refresh) except AccessCodeUsed: err = TokenErrorResponse(error="invalid_grant", error_description="Access grant used") return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("_tinfo: %s" % _tinfo) atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo)) logger.debug("AccessTokenResponse: %s" % atr) return Response(atr.to_json(), content="application/json")
def token_endpoint(self, authn="", **kwargs): """ This is where clients come to get their access tokens """ _sdb = self.sdb logger.debug("- token -") body = kwargs["request"] logger.debug("body: %s" % body) areq = AccessTokenRequest().deserialize(body, "urlencoded") try: client = self.client_authn(self, areq, authn) except FailedAuthentication as err: err = TokenErrorResponse(error="unauthorized_client", error_description="%s" % err) return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("AccessTokenRequest: %s" % areq) try: assert areq["grant_type"] == "authorization_code" except AssertionError: err = TokenErrorResponse(error="invalid_request", error_description="Wrong grant type") return Response(err.to_json(), content="application/json", status="401 Unauthorized") # assert that the code is valid _info = _sdb[areq["code"]] resp = self.token_scope_check(areq, _info) if resp: return resp # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _info: assert areq["redirect_uri"] == _info["redirect_uri"] try: _tinfo = _sdb.upgrade_to_token(areq["code"], issue_refresh=True) except AccessCodeUsed: err = TokenErrorResponse(error="invalid_grant", error_description="Access grant used") return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("_tinfo: %s" % _tinfo) atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo)) logger.debug("AccessTokenResponse: %s" % atr) return Response(atr.to_json(), content="application/json")
def test_flow(): cli = PoPClient() # Client creates access token request atreq = AccessTokenRequest(grant_type="authorization_code", code="SplxlOBeZQQYbYS6WxSbIA", redirect_uri="https://client.example.com/cb") # adds key information, also connects the new key to the state value used atreq = cli.update(atreq, 'state') assert 'key' in atreq pas = PoPAS('https://example.com/as') pas.keyjar = init_keyjar() # Key is in the JSON string representation finger_print = pas.store_key(json.loads(atreq['key'])) access_token = pas.create_access_token(finger_print) # The AS constructs the access token response atrsp = AccessTokenResponse(access_token=access_token, token_type="bearer", state='state') # The client receives the response and connects the key to the access token cli.handle_access_token_response(atrsp) assert access_token in cli.token2key assert cli.token2key[access_token] == cli.state2key['state'] # Time for the client to access the Resource Server url = 'https://example.com/rs?foo=bar&format=json' headers = {'Content-type': 'application/www-form-encoded'} body = 'access_token={}'.format(access_token) # creates the POP token using signed HTTP request cb = PoPCallBack(cli.token2key[atrsp['access_token']], cli.alg) kwargs = cb('POST', url, headers=headers, body=body) assert kwargs['Authorization'].startswith('pop ') pop_token = kwargs['Authorization'][4:] assert len(pop_token.split('.')) == 3 # simple JWS check # now to the RS rs = PoPRS() # The AS gets a token introspection request # verifies the correctness of the access token # and if correct constructs the token introspection response tir = pas.token_introspection(atrsp['access_token']) # The RS binds the received key to the access token rs.store_key(access_token, tir) # The RS verifies the correctness of the POP token res = rs.eval_signed_http_request(pop_token, access_token, 'POST', url, headers, body) # YEY :-) assert res
def do_access_token_response(self, access_token, atinfo, state, refresh_token=None): _tinfo = {'access_token': access_token, 'expires_in': atinfo['exp'], 'token_type': 'bearer', 'state': state} try: _tinfo['scope'] = atinfo['scope'] except KeyError: pass if refresh_token: _tinfo['refresh_token'] = refresh_token return AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo))
def token_endpoint(self, authn="", **kwargs): """ This is where clients come to get their access tokens """ _sdb = self.sdb logger.debug("- token -") body = kwargs["request"] logger.debug("body: %s" % body) areq = AccessTokenRequest().deserialize(body, "urlencoded") try: client_id = self.client_authn(self, areq, authn) except FailedAuthentication as err: err = TokenErrorResponse(error="unauthorized_client", error_description="%s" % err) return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("AccessTokenRequest: %s" % areq) # assert that the code is valid try: _info = _sdb[areq["code"]] except KeyError: err = TokenErrorResponse(error="invalid_grant", error_description="Unknown access grant") return Response(err.to_json(), content="application/json", status="401 Unauthorized") authzreq = json.loads(_info['authzreq']) if 'code_verifier' in areq: try: _method = authzreq['code_challenge_method'] except KeyError: _method = 'S256' resp = self.verify_code_challenge(areq['code_verifier'], authzreq['code_challenge'], _method) if resp: return resp try: assert areq["grant_type"] == "authorization_code" except AssertionError: err = TokenErrorResponse(error="invalid_request", error_description="Wrong grant type") return Response(err.to_json(), content="application/json", status="401 Unauthorized") if 'state_hash' in areq: # have to get the token to get at the state code = areq['code'] shash = base64.urlsafe_b64encode( hashlib.sha256( self.sdb[code]['state'].encode('utf8')).digest()) if shash.decode('ascii') != areq['state_hash']: err = TokenErrorResponse(error="unauthorized_client") return Unauthorized(err.to_json(), content="application/json") resp = self.token_scope_check(areq, _info) if resp: return resp # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _info: assert areq["redirect_uri"] == _info["redirect_uri"] issue_refresh = False if 'scope' in authzreq and 'offline_access' in authzreq['scope']: if authzreq['response_type'] == 'code': issue_refresh = True try: _tinfo = _sdb.upgrade_to_token(areq["code"], issue_refresh=issue_refresh) except AccessCodeUsed: err = TokenErrorResponse(error="invalid_grant", error_description="Access grant used") return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("_tinfo: %s" % _tinfo) atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo)) logger.debug("AccessTokenResponse: %s" % atr) return Response(atr.to_json(), content="application/json")
def refresh_token_grant_type(self, areq): at = self.token_handler.refresh_access_token( self.baseurl, areq['access_token'], 'refresh_token') atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **at)) return Response(atr.to_json(), content="application/json")