def test_revoke_token(self): ae1 = AuthnEvent("uid", "salt") sid = self.sdb.create_authz_session(ae1, AREQ) self.sdb[sid]['sub'] = 'sub' grant = self.sdb[sid]["code"] tokens = self.sdb.upgrade_to_token(grant, issue_refresh=True) access_token = tokens["access_token"] refresh_token = tokens["refresh_token"] assert self.sdb.is_valid(access_token) self.sdb.revoke_token(access_token) assert not self.sdb.is_valid(access_token) sinfo = self.sdb.refresh_token(refresh_token, AREQ['client_id']) access_token = sinfo["access_token"] assert self.sdb.is_valid(access_token) self.sdb.revoke_refresh_token(refresh_token) assert not self.sdb.is_valid(refresh_token) try: self.sdb.refresh_token(refresh_token, AREQ['client_id']) except ExpiredToken: pass assert self.sdb.is_valid(access_token) ae2 = AuthnEvent("sub", "salt") sid = self.sdb.create_authz_session(ae2, AREQ) grant = self.sdb[sid]["code"] self.sdb.revoke_token(grant) assert not self.sdb.is_valid(grant)
def test_token_endpoint_malformed(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id=CLIENT_ID, response_type="code", scope=["openid"]) _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) ae = AuthnEvent("user", "salt") _sdb[sid] = { "oauth_state": "authz", "authn_event": ae.to_json(), "authzreq": authreq.to_json(), "client_id": CLIENT_ID, "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } _sdb.do_sub(sid, "client_salt") # Construct Access token request areq = AccessTokenRequest(code=access_grant[0:len(access_grant) - 1], client_id=CLIENT_ID, redirect_uri="http://example.com/authz", client_secret=CLIENT_SECRET, grant_type='authorization_code') txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr['error'] == "invalid_request"
def test_revoke_token(self): ae1 = AuthnEvent("sub", "salt") sid = self.sdb.create_authz_session(ae1, AREQ) grant = self.sdb[sid]["code"] tokens = self.sdb.upgrade_to_token(grant) access_token = tokens["access_token"] refresh_token = tokens["refresh_token"] assert self.sdb.is_valid(access_token) self.sdb.revoke_token(access_token) assert not self.sdb.is_valid(access_token) refreshed_tokens = self.sdb.refresh_token(refresh_token) access_token = refreshed_tokens["access_token"] assert self.sdb.is_valid(access_token) self.sdb.revoke_token(refresh_token) assert not self.sdb.is_valid(refresh_token) with pytest.raises(ExpiredToken): self.sdb.refresh_token(refresh_token) assert self.sdb.is_valid(access_token) ae2 = AuthnEvent("sub", "salt") sid = self.sdb.create_authz_session(ae2, AREQ) grant = self.sdb[sid]["code"] self.sdb.revoke_token(grant) assert not self.sdb.is_valid(grant)
def test_sub_to_authn_event(self): ae = AuthnEvent("sub", "salt", time_stamp=time.time()) sid = self.sdb.create_authz_session(ae, AREQ) sub = self.sdb.do_sub(sid, "client_salt") # given the sub find out whether the authn event is still valid sids = self.sdb.get_sids_by_sub(sub) ae = self.sdb[sids[0]]["authn_event"] assert AuthnEvent.from_json(ae).valid()
def test_sub_to_authn_event(self): ae = AuthnEvent("sub", "salt", time_stamp=time.time()) sid = self.sdb.create_authz_session(ae, AREQ) sub = self.sdb.do_sub(sid, "client_salt") # given the sub find out whether the authn event is still valid sids = self.sdb.get_sids_by_sub(sub) ae = self.sdb[sids[0]]["authn_event"] assert ae.valid()
def test_to_json(self): ae = AuthnEvent('uid', 'salt', authn_time=1000, valid_until=1500) json_repr = ae.to_json() assert json.loads(json_repr) == { 'uid': 'uid', 'salt': 'salt', 'authn_time': 1000, 'valid_until': 1500, 'authn_info': None }
def test_to_json(self): ae = AuthnEvent("uid", "salt", authn_time=1000, valid_until=1500) json_repr = ae.to_json() assert json.loads(json_repr) == { "uid": "uid", "salt": "salt", "authn_time": 1000, "valid_until": 1500, "authn_info": None, }
def test_get_by_uid_multiple(self): aevent1 = AuthnEvent("my_uid", "some_salt").to_json() aevent2 = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id1": { "authn_event": aevent1 }, "session_id2": { "authn_event": aevent2 } } self.assertEqual(set(self.backend.get_by_uid("my_uid")), {"session_id1", "session_id2"})
def test_is_revoke_uid_multiple(self): aevent1 = AuthnEvent("my_uid", "some_salt").to_json() aevent2 = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id1": { "authn_event": aevent1, "revoked": True }, "session_id2": { "authn_event": aevent2, "revoked": False } } self.assertTrue(self.backend.is_revoke_uid("my_uid"))
def test_get_client_ids_for_uid_multiple(self): aevent1 = AuthnEvent("my_uid", "some_salt").to_json() aevent2 = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id1": { "authn_event": aevent1, "client_id": "my_client" }, "session_id2": { "authn_event": aevent2, "client_id": "my_other" } } self.assertEqual(set(self.backend.get_client_ids_for_uid("my_uid")), {"my_client", "my_other"})
def test_get_token_ids_multiple(self): aevent1 = AuthnEvent("my_uid", "some_salt").to_json() aevent2 = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id1": { "authn_event": aevent1, "id_token": "Id token 1" }, "session_id2": { "authn_event": aevent2, "id_token": "Id token 2" } } self.assertEqual(set(self.backend.get_token_ids("my_uid")), {"Id token 1", "Id token 2"})
def test_get_verified_logout_multiple(self): aevent1 = AuthnEvent("my_uid", "some_salt").to_json() aevent2 = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id1": { "authn_event": aevent1, "verified_logout": "verification key" }, "session_id2": { "authn_event": aevent2, "verified_logout": "verification key" } } self.assertEqual(self.backend.get_verified_logout("my_uid"), "verification key")
def password_grant_type(self, areq): """ Token authorization using Resource owner password credentials. RFC6749 section 4.3 """ # `Any` comparison tries a first broker, so we either hit an IndexError or get a method try: authn, authn_class_ref = self.pick_auth(areq, "any") except IndexError: err = TokenErrorResponse(error="invalid_grant") return Unauthorized(err.to_json(), content="application/json") identity, _ts = authn.authenticated_as( username=areq["username"], password=areq["password"] ) if identity is None: err = TokenErrorResponse(error="invalid_grant") return Unauthorized(err.to_json(), content="application/json") # We are returning a token areq["response_type"] = ["token"] authn_event = AuthnEvent( identity["uid"], identity.get("salt", ""), authn_info=authn_class_ref, time_stamp=_ts, ) sid = self.setup_session(areq, authn_event, self.cdb[areq["client_id"]]) _at = self.sdb.upgrade_to_token(self.sdb[sid]["code"], issue_refresh=True) atr_class = self.server.message_factory.get_response_type("token_endpoint") atr = atr_class(**by_schema(atr_class, **_at)) return Response( atr.to_json(), content="application/json", headers=OAUTH2_NOCACHE_HEADERS )
def test_get_verified_logout(self): aevent1 = AuthnEvent("my_uid1", "some_salt").to_json() aevent2 = AuthnEvent("my_uid2", "some_salt").to_json() self.backend.storage = { "session_id": { "authn_event": aevent1, "verified_logout": "verification key", }, "session_id2": { "authn_event": aevent2 }, } self.assertEqual(self.backend.get_verified_logout("my_uid1"), "verification key") self.assertIsNone(self.backend.get_verified_logout("my_uid2")) self.assertIsNone(self.backend.get_verified_logout("missing"))
def test_upgrade_to_token(self): ae1 = AuthnEvent("uid", "salt") sid = self.sdb.create_authz_session(ae1, AREQ) self.sdb[sid]["sub"] = "sub" grant = self.sdb[sid]["code"] _dict = self.sdb.upgrade_to_token(grant) assert _eq( list(_dict.keys()), [ "authn_event", "code", "authzreq", "revoked", "access_token", "token_type", "state", "redirect_uri", "code_used", "client_id", "scope", "oauth_state", "access_token_scope", "sub", "response_type", ], ) # can't update again with pytest.raises(AccessCodeUsed): self.sdb.upgrade_to_token(grant) self.sdb.upgrade_to_token(_dict["access_token"])
def test_upgrade_to_token_refresh(self): ae1 = AuthnEvent("sub", "salt") sid = self.sdb.create_authz_session(ae1, AREQO) self.sdb.do_sub(sid, ae1.salt) grant = self.sdb[sid]["code"] _dict = self.sdb.upgrade_to_token(grant, issue_refresh=True) assert _eq( _dict.keys(), [ "authn_event", "code", "authzreq", "revoked", "access_token", "response_type", "token_type", "state", "redirect_uri", "code_used", "client_id", "scope", "oauth_state", "access_token_scope", "refresh_token", "sub", ], ) # can't update again with pytest.raises(AccessCodeUsed): self.sdb.upgrade_to_token(grant) self.sdb.upgrade_to_token(_dict["access_token"])
def test_upgrade_to_token_with_id_token_and_oidreq(self): ae2 = AuthnEvent("another_user_id", "salt") sid = self.sdb.create_authz_session(ae2, AREQ) self.sdb[sid]["sub"] = "sub" grant = self.sdb[sid]["code"] _dict = self.sdb.upgrade_to_token(grant, id_token="id_token", oidreq=OIDR) assert _eq( list(_dict.keys()), [ "authn_event", "code", "authzreq", "revoked", "oidreq", "access_token", "id_token", "response_type", "token_type", "state", "redirect_uri", "code_used", "client_id", "scope", "oauth_state", "access_token_scope", "sub", ], ) assert _dict["id_token"] == "id_token" assert isinstance(_dict["oidreq"], OpenIDRequest)
def test_from_json(self): dic = {'uid': 'uid', 'salt': 'salt', 'authn_time': 1000, 'valid_until': 1500} ae = AuthnEvent.from_json(json.dumps(dic)) assert ae.uid == 'uid' assert ae.salt == 'salt' assert ae.authn_time == 1000 assert ae.valid_until == 1500
def test_do_sub_deterministic(self): ae = AuthnEvent("tester", "random_value") sid = self.sdb.create_authz_session(ae, AREQ) self.sdb.do_sub(sid, "other_random_value") info = self.sdb[sid] assert info["sub"] == \ '179670cdee6375c48e577317b2abd7d5cd26a5cdb1cfb7ef84af3d703c71d013' self.sdb.do_sub(sid, "other_random_value", sector_id='http://example.com', subject_type="pairwise") info2 = self.sdb[sid] assert info2["sub"] == \ 'aaa50d80f8780cf1c4beb39e8e126556292f5091b9e39596424fefa2b99d9c53' self.sdb.do_sub(sid, "another_random_value", sector_id='http://other.example.com', subject_type="pairwise") info2 = self.sdb[sid] assert info2["sub"] == \ '62fb630e29f0d41b88e049ac0ef49a9c3ac5418c029d6e4f5417df7e9443976b'
def test_create_authz_session(self): ae = AuthnEvent("uid", "salt") sid = self.sdb.create_authz_session(ae, AREQ) self.sdb.do_sub(sid, "client_salt") info = self.sdb[sid] assert info["oauth_state"] == "authz"
def setup_token_endpoint(self): authreq = AuthorizationRequest(state="state", redirect_uri=self.redirect_urls[0], client_id=CLIENT_ID, response_type="code", scope=["openid"]) _sdb = self.provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) ae = AuthnEvent("user", "salt") _sdb[sid] = { "oauth_state": "authz", "authn_event": ae, "authzreq": authreq.to_json(), "client_id": CLIENT_ID, "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": self.redirect_urls[0], } _sdb.do_sub(sid, "client_salt") # Construct Access token request areq = AccessTokenRequest(code=access_grant, client_id=CLIENT_ID, redirect_uri=self.redirect_urls[0], client_secret="client_secret_1") txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) responses.add(responses.POST, self.op_base + "token", body=resp.message, status=200, content_type='application/json')
def test_token_endpoint(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id=CLIENT_ID, response_type="code", scope=["openid"]) _sdb = self.provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) ae = AuthnEvent("user", "salt") _sdb[sid] = { "oauth_state": "authz", "authn_event": ae, "authzreq": authreq.to_json(), "client_id": CLIENT_ID, "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } _sdb.do_sub(sid, "client_salt") # Construct Access token request areq = AccessTokenRequest(code=access_grant, client_id=CLIENT_ID, redirect_uri="http://example.com/authz", client_secret=CLIENT_SECRET) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = AccessTokenResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ['token_type', 'id_token', 'access_token', 'scope', 'expires_in', 'refresh_token'])
def test_token_endpoint_unauth(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client_1") _sdb = self.provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) ae = AuthnEvent("user", "salt") _sdb[sid] = { "authn_event": ae, "oauth_state": "authz", "authzreq": "", "client_id": "client_1", "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz" } _sdb.do_sub(sid, "client_salt") # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id="client_1", client_secret="secret", ) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt, remote_user="******", request_method="POST") atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr["error"] == "unauthorized_client"
def test_refresh_access_token_request(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id=CLIENT_ID, response_type="code", scope=["openid", 'offline_access'], prompt='consent') _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) ae = AuthnEvent("user", "salt") _sdb[sid] = { "oauth_state": "authz", "authn_event": ae.to_json(), "authzreq": authreq.to_json(), "client_id": CLIENT_ID, "code": access_grant, "code_used": False, "scope": ["openid", 'offline_access'], "redirect_uri": "http://example.com/authz", } _sdb.do_sub(sid, "client_salt") # Construct Access token request areq = AccessTokenRequest(code=access_grant, client_id=CLIENT_ID, redirect_uri="http://example.com/authz", client_secret=CLIENT_SECRET, grant_type='authorization_code') txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = AccessTokenResponse().deserialize(resp.message, "json") rareq = RefreshAccessTokenRequest(grant_type="refresh_token", refresh_token=atr['refresh_token'], client_id=CLIENT_ID, client_secret=CLIENT_SECRET, scope=['openid']) resp = self.provider.token_endpoint(request=rareq.to_urlencoded()) atr2 = AccessTokenResponse().deserialize(resp.message, "json") assert atr2['access_token'] != atr['access_token'] assert atr2['refresh_token'] == atr['refresh_token'] assert atr2['token_type'] == 'Bearer'
def test_is_revoke_uid_true(self): aevent = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id": { "authn_event": aevent, "revoked": True } } self.assertTrue(self.backend.is_revoke_uid("my_uid"))
def test_server_authorization_endpoint_id_token(): provider = provider_init bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087/authz", "response_type": ["code", "id_token"], "client_id": "a1b2c3", "nonce": "Nonce", "prompt": ["none"] } req = AuthorizationRequest(**bib) areq = AuthorizationRequest(response_type="code", client_id="client_1", redirect_uri="http://example.com/authz", scope=["openid"], state="state000") sdb = provider.sdb ae = AuthnEvent("userX") sid = sdb.create_authz_session(ae, areq) sdb.do_sub(sid) _info = sdb[sid] # All this is jut removed when the id_token is constructed # The proper information comes from the session information _user_info = IdToken(iss="https://foo.example.om", sub="foo", aud=bib["client_id"], exp=epoch_in_a_while(minutes=10), acr="2", nonce=bib["nonce"]) print provider.keyjar.issuer_keys print _user_info.to_dict() idt = provider.id_token_as_signed_jwt(_info, access_token="access_token", user_info=_user_info) req["id_token"] = idt query_string = req.to_urlencoded() # client_id not in id_token["aud"] so login required resp = provider.authorization_endpoint(request=query_string, cookie="FAIL") print resp assert "error=login_required" in resp.message req["client_id"] = "client_1" query_string = req.to_urlencoded() # client_id is in id_token["aud"] so no login required resp = provider.authorization_endpoint(request=query_string, cookie="FAIL") print resp.message assert resp.message.startswith("http://localhost:8087/authz")
def authorization_endpoint(self, query): req = self.parse_authorization_request(query=query) aevent = AuthnEvent("user", "salt", authn_info="acr") sid = self.sdb.create_authz_session(aevent, areq=req) self.sdb.do_sub(sid, 'client_salt') _info = self.sdb[sid] if "code" in req["response_type"]: if "token" in req["response_type"]: grant = _info["code"] _dict = self.sdb.upgrade_to_token(grant) _dict["oauth_state"] = "authz", _dict = by_schema(AuthorizationResponse(), **_dict) resp = AuthorizationResponse(**_dict) # resp.code = grant else: _state = req["state"] resp = AuthorizationResponse(state=_state, code=_info["code"]) else: # "implicit" in req.response_type: grant = _info["code"] params = AccessTokenResponse.c_param.keys() if "token" in req["response_type"]: _dict = dict([ (k, v) for k, v in self.sdb.upgrade_to_token(grant).items() if k in params ]) try: del _dict["refresh_token"] except KeyError: pass else: _dict = {"state": req["state"]} if "id_token" in req["response_type"]: _idt = self.make_id_token(_info, issuer=self.name) alg = "RS256" ckey = self.keyjar.get_signing_key(alg2keytype(alg), _info["client_id"]) _signed_jwt = _idt.to_jwt(key=ckey, algorithm=alg) p = _signed_jwt.split(".") p[2] = "aaa" _dict["id_token"] = ".".join(p) resp = AuthorizationResponse(**_dict) location = resp.request(req["redirect_uri"]) response = Response() response.headers = {"location": location} response.status_code = 302 response.text = "" return response
def test_is_valid(): sdb = SessionDB(BASE_URL) ae1 = AuthnEvent("sub") sid = sdb.create_authz_session(ae1, AREQ) grant = sdb[sid]["code"] assert sdb.is_valid(grant) _dict = sdb.upgrade_to_token(grant) assert sdb.is_valid(grant) is False token1 = _dict["access_token"] assert sdb.is_valid(token1) rtoken = _dict["refresh_token"] assert sdb.is_valid(rtoken) dict2 = sdb.refresh_token(rtoken) token2 = dict2["access_token"] assert sdb.is_valid(token2) # replace refresh_token dict2["refresh_token"] = token2 assert sdb.is_valid(rtoken) is False # mess with the time-line dict2["token_expires_at"] = utc_time_sans_frac() - 86400 assert sdb.is_valid(token2) is False # replace access_token dict2["access_token"] = token1 assert sdb.is_valid(token2) is False ae = AuthnEvent("another:user") sid = sdb.create_authz_session(ae, AREQ) grant = sdb[sid]["code"] gdict = sdb[grant] gdict["token_expires_at"] = utc_time_sans_frac() - 86400 assert sdb.is_valid(grant) is False
def test_get_token_ids(self): aevent = AuthnEvent("my_uid", "some_salt").to_json() self.backend.storage = { "session_id": { "authn_event": aevent, "id_token": "Id token" } } self.assertEqual(set(self.backend.get_token_ids("my_uid")), {"Id token"}) self.assertEqual(set(self.backend.get_token_ids("missing")), set())
def test_sub_to_authn_event(): sdb = SessionDB(BASE_URL) ae2 = AuthnEvent("sub", time_stamp=time.time()) sid = sdb.create_authz_session(ae2, AREQ) sub = sdb.do_sub(sid) # given the sub find out weather the authn event is still valid sids = sdb.get_sids_by_sub(sub) ae = sdb[sids[0]]["authn_event"] assert ae.valid()
def test_token_endpoint_ok_state(self): authreq = AuthorizationRequest( state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type="code", scope=["openid"], ) _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) ae = AuthnEvent("user", "salt") _sdb[sid] = { "oauth_state": "authz", "authn_event": ae.to_json(), "authzreq": "", "client_id": "client1", "code": access_grant, "state": "state", "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } _sdb.do_sub(sid, "client_salt") # Construct Access token request areq = AccessTokenRequest( code=access_grant, client_id="client1", redirect_uri="http://example.com/authz", client_secret="hemlighet", grant_type="authorization_code", state="state", ) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = AccessTokenResponse().deserialize(resp.message, "json") assert atr["token_type"] == "Bearer"
def test_to_json(self): ae = AuthnEvent('uid', 'salt', authn_time=1000, valid_until=1500) json_repr = ae.to_json() assert json.loads(json_repr) == {'uid': 'uid', 'salt': 'salt', 'authn_time': 1000, 'valid_until': 1500, 'authn_info': None}