def __init__(self, name, sdb, cdb, authn_method, userinfo, authz, client_authn, symkey, urlmap=None, ca_certs="", keyjar=None, hostname=""): AProvider.__init__(self, name, sdb, cdb, authn_method, authz, client_authn, symkey, urlmap) self.userinfo = userinfo self.server = Server(ca_certs=ca_certs) if keyjar: self.server.keyjar = keyjar self.keyjar = self.server.keyjar self.endpoints = [] self.baseurl = "" self.cert = [] self.cert_encryption = [] if authn_method: self.cookie_func = authn_method.create_cookie else: self.cookie_func = None self.cookie_name = "pyoidc" self.seed = "" self.sso_ttl = 0 self.test_mode = False self.jwks_uri = [] self.authn_as = None self.preferred_id_type = "public" self.hostname = hostname or socket.gethostname self.register_endpoint = "%s%s" % (self.baseurl, "register")
def test_provider_authenticated_token(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) _session_db = {} cons = Consumer(_session_db, client_config = CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True cons.response_type = "token" environ = BASE_ENVIRON location = cons.begin(environ, start_response) environ = BASE_ENVIRON.copy() environ["QUERY_STRING"] = location.split("?")[1] resp = provider.authorization_endpoint(environ, start_response) sid = resp[0][len("FORM with "):] environ2 = create_return_form_env("user", "password", sid) resp2 = provider.authenticated(environ2, start_response) assert len(resp2) == 1 txt = resp2[0] assert "access_token=" in txt assert "token_type=Bearer" in txt
def test_provider_authenticated(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ, verify_client, symkey=rndstr(16)) _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") query_string = location.split("?")[1] resp = provider.authorization_endpoint(query_string) assert resp.status == "302 Found" print resp.headers print resp.message if content_type(resp.headers) == "json": resp = resp.message else: resp = resp.message.split("?")[1] aresp = cons.handle_authorization_response(query=resp) print aresp.keys() assert aresp.type() == "AuthorizationResponse" assert _eq(aresp.keys(), ['state', 'code']) print cons.grant[cons.state].keys() assert _eq(cons.grant[cons.state].keys(), ['tokens', 'code', 'exp_in', 'seed', 'id_token', 'grant_expiration_time'])
def test_complete_authz_pyoidc_cookie_exists(self, session_db_factory): provider = Provider("pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') areq = { 'client_id': 'client1', 'response_type': ['code'], 'redirect_uri': 'http://localhost:8087/authz' } sid = provider.sdb.access_token.key(user='******', areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { 'oauth_state': 'authz', 'sub': 'sub', 'client_id': 'client1', 'code': access_code, 'redirect_uri': 'http://localhost:8087/authz' } cookie = 'pyoidc_sso=test::test' response, header, redirect, fragment = provider._complete_authz( 'sub', areq, sid, cookie=cookie) assert len(header) == 0 assert not fragment assert redirect == 'http://localhost:8087/authz' assert 'code' in response
def test_provider_authenticated_none(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) _session_db = {} cons = Consumer(_session_db, client_config = CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True cons.response_type = "none" environ = BASE_ENVIRON location = cons.begin(environ, start_response) environ = BASE_ENVIRON.copy() environ["QUERY_STRING"] = location.split("?")[1] resp = provider.authorization_endpoint(environ, start_response) sid = resp[0][len("FORM with "):] environ2 = create_return_form_env("user", "password", sid) resp2 = provider.authenticated(environ2, start_response) assert len(resp2) == 1 txt = resp2[0] pos0 = txt.index("<title>") + len("<title>Redirecting to ") pos1 = txt.index("</title>") location = txt[pos0:pos1] print location assert location.startswith("http://localhost:8087/authz") query = location.split("?")[1] assert query.startswith("state=") assert "&" not in query
def __init__(self, name, sdb, cdb, authn_broker, userinfo, authz, client_authn, symkey, urlmap=None, ca_certs="", keyjar=None, hostname="", template_lookup=None, verify_login_template=None): AProvider.__init__(self, name, sdb, cdb, authn_broker, authz, client_authn, symkey, urlmap) self.endp.extend([UserinfoEndpoint, RegistrationEndpoint, EndSessionEndpoint]) self.userinfo = userinfo self.server = Server(ca_certs=ca_certs) if keyjar: self.server.keyjar = keyjar self.template_lookup = template_lookup self.verify_login_template = verify_login_template self.keyjar = self.server.keyjar self.baseurl = "" self.cert = [] self.cert_encryption = [] self.cookie_name = "pyoidc" self.seed = "" self.sso_ttl = 0 self.test_mode = False self.jwks_uri = [] self.authn_as = None self.preferred_id_type = "public" self.hostname = hostname or socket.gethostname self.register_endpoint = "%s%s" % (self.baseurl, "register")
def test_token_endpoint_unauth(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ, verify_client, symkey=rndstr(16)) authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "user_id": "user_id", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id="client2", client_secret="hemlighet",) print areq.to_dict() resp = provider.token_endpoint(request=areq.to_urlencoded()) print resp.message atr = TokenErrorResponse().deserialize(resp.message, "json") print atr.keys() assert _eq(atr.keys(), ['error_description', 'error'])
def test_provider_authenticated_token(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ, verify_client) _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization", "token") QUERY_STRING = location.split("?")[1] resp = provider.authorization_endpoint(QUERY_STRING) print resp.headers print resp.message txt = resp.message assert "access_token=" in txt assert "token_type=Bearer" in txt
def test_provider_init(): provider = Provider("pyoicserv", sdb.SessionDB(SERVER_INFO["issuer"]), CDB, AUTHN_BROKER, AUTHZ, verify_client) assert provider provider = Provider("pyoicserv", sdb.SessionDB(SERVER_INFO["issuer"]), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}) assert provider.urlmap["client1"] == ["https://example.com/authz"]
def test_provider_authenticated(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) _session_db = {} cons = Consumer(_session_db, client_config = CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True environ = BASE_ENVIRON location = cons.begin(environ, start_response) environ = BASE_ENVIRON.copy() environ["QUERY_STRING"] = location.split("?")[1] resp = provider.authorization_endpoint(environ, start_response) sid = resp[0][len("FORM with "):] environ2 = create_return_form_env("user", "password", sid) resp2 = provider.authenticated(environ2, start_response) print resp2[0] assert len(resp2) == 1 txt = resp2[0] pos0 = txt.index("<title>") + len("<title>Redirecting to ") pos1 = txt.index("</title>") location = txt[pos0:pos1] print location assert location.startswith("http://localhost:8087/authz") environ = BASE_ENVIRON.copy() environ["QUERY_STRING"] = location.split("?")[1] aresp = cons.handle_authorization_response(environ, start_response) #aresp = client.parse_response(AuthorizationResponse, location, # format="urlencoded", # state="id-6da9ca0cc23959f5f33e8becd9b08cae") print aresp.keys() assert aresp.type() == "AuthorizationResponse" assert _eq(aresp.keys(), ['state', 'code']) print cons.grant[cons.state].keys() assert _eq(cons.grant[cons.state].keys(), ['tokens', 'code', 'exp_in', 'seed', 'id_token', 'grant_expiration_time'])
def test_provider_authorization_endpoint(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ, verify_client) bib = {"scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087authz", "response_type": ["code"], "client_id": "a1b2c3"} arq = AuthorizationRequest(**bib) QUERY_STRING = arq.to_urlencoded() resp = provider.authorization_endpoint(request=QUERY_STRING) assert isinstance(resp, Response)
def test_failed_authenticated(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) environ0 = create_return_form_env("haden", "secret", "sid1") resp1 = provider.authenticated(environ0, start_response) print resp1 assert resp1 == ['<html>Wrong password</html>'] environ1 = create_return_form_env("", "secret", "sid2") resp2 = provider.authenticated(environ1, start_response) print resp2 assert resp2 == ["<html>Authentication failed</html>"] environ2 = create_return_form_env("hannibal", "hemligt", "sid3") print environ2 resp = provider.authenticated(environ2, start_response) print resp assert resp == ['<html>Authentication failure: Not allowed to use this service (hannibal)</html>']
def test_provider_authorization_endpoint(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) bib = {"scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087authz", "response_type": ["code"], "client_id": "a1b2c3"} arq = AuthorizationRequest(**bib) environ = BASE_ENVIRON.copy() environ["QUERY_STRING"] = arq.to_urlencoded() resp = provider.authorization_endpoint(environ, start_response) print resp assert resp[0].startswith("FORM with")
def test_provider_authenticated_1(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) _session_db = {} cons = Consumer(_session_db, client_config = CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True environ = BASE_ENVIRON location = cons.begin(environ, start_response) environ = BASE_ENVIRON.copy() environ["QUERY_STRING"] = location.split("?")[1] _ = provider.authorization_endpoint(environ, start_response) #sid = resp[0][len("FORM with "):] environ2 = create_return_form_env("user", "password", "abcd") resp2 = provider.authenticated(environ2, start_response) print resp2 assert resp2 == ['<html>Unknown session identifier</html>']
def test_init(self, session_db_factory): provider = Provider( "pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, ) assert provider provider = Provider( "pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}, ) assert provider.urlmap["client1"] == ["https://example.com/authz"]
def test_token_endpoint(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, FUNCTIONS) authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "user_id": "user_id", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri":"http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz") str = areq.to_urlencoded() fil = StringIO.StringIO(buf=str) environ = BASE_ENVIRON.copy() environ["CONTENT_LENGTH"] = len(str) environ["wsgi.input"] = fil environ["REMOTE_USER"] = "******" resp = provider.token_endpoint(environ, start_response) print resp atr = AccessTokenResponse().deserialize(resp[0], "json") print atr.keys() assert _eq(atr.keys(), ['access_token', 'expires_in', 'token_type', 'refresh_token'])
def __init__(self, name, sdb, cdb, function, userdb, urlmap=None, ca_certs="", jwt_keys=None): AProvider.__init__(self, name, sdb, cdb, function, urlmap) self.server = Server(jwt_keys=jwt_keys, ca_certs=ca_certs) self.keystore = self.server.keystore self.userdb = userdb self.function = function self.endpoints = [] self.baseurl = "" self.cert = [] self.cert_encryption = [] self.cookie_func = None self.cookie_name = "pyoidc" self.seed = "" self.cookie_ttl = 0 self.test_mode = False self.jwk = []
def test_provider_authenticated_none(): provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN, AUTHZ, verify_client) _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization", "none") QUERY_STRING = location.split("?")[1] resp2 = provider.authorization_endpoint(request=QUERY_STRING) location = resp2.message print location assert location.startswith("http://localhost:8087/authz") query = location.split("?")[1] assert query.startswith("state=") assert "&" not in query
def create_provider(self): self.provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as')
class TestProvider(object): @pytest.fixture(autouse=True) def create_provider(self): self.provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') def test_init(self): provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client) assert provider provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}) assert provider.urlmap["client1"] == ["https://example.com/authz"] def test_authorization_endpoint_faulty_redirect_uri(self): bib = {"scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087/authz", # faulty redirect uri "response_type": ["code"], "client_id": "a1b2c3"} arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint(request=arq.to_urlencoded()) assert resp.status == "400 Bad Request" msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authenticated(self): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") resp = self.provider.authorization_endpoint(urlparse(location).query) assert resp.status == "303 See Other" resp = urlparse(resp.message).query aresp = cons.handle_authorization_response(query=resp) assert isinstance(aresp, AuthorizationResponse) assert _eq(aresp.keys(), ['state', 'code', 'client_id', 'iss']) assert _eq(cons.grant[sid].keys(), ['tokens', 'code', 'exp_in', 'seed', 'id_token', 'grant_expiration_time']) def test_authenticated_token(self): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization", "token") QUERY_STRING = location.split("?")[1] resp = self.provider.authorization_endpoint(QUERY_STRING) auth_resp = parse_qs(urlparse(resp.message).fragment) assert "access_token" in auth_resp assert auth_resp["token_type"][0] == "Bearer" def test_token_endpoint(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id="client1", client_secret="hemlighet", grant_type='authorization_code') resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = AccessTokenResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ['access_token', 'token_type', 'refresh_token']) def test_token_endpoint_unauth(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id="client2", client_secret="hemlighet", grant_type='authorization_code') resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = TokenErrorResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ['error_description', 'error'])
from oic.utils.sdb import SessionDB parser = argparse.ArgumentParser() parser.add_argument('-v', dest='verbose', action='store_true') parser.add_argument('-d', dest='debug', action='store_true') parser.add_argument('-p', dest='port', default=80, type=int) parser.add_argument('-A', dest='authn_as', default="") parser.add_argument('-P', dest='provider_conf') parser.add_argument(dest="config") args = parser.parse_args() config = importlib.import_module(args.config) OAS = Provider(config.issuer, SessionDB(), config.CLIENT, FUNCTIONS, config.USERDB) try: OAS.cookie_ttl = config.COOKIETTL except AttributeError: pass try: OAS.cookie_name = config.COOKIENAME except AttributeError: pass OAS.cookie_func = http_util.cookie #print URLS if args.debug:
class TestProvider(object): @pytest.fixture(autouse=True) def create_provider(self, session_db_factory): self.provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') def test_init(self, session_db_factory): provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client) assert provider provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}) assert provider.urlmap["client1"] == ["https://example.com/authz"] def test_authorization_endpoint_faulty_redirect_uri(self): bib = {"scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://*****:*****@pytest.mark.parametrize("response_types", [ ['token id_token', 'id_token'], ['id_token token'] ]) def test_response_types(self, response_types): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type='id_token token') self.provider.cdb = { "client1": { "client_secret": "hemlighet", "redirect_uris": [("http://example.com/authz", None)], 'token_endpoint_auth_method': 'client_secret_post', 'response_types': response_types } } res = self.provider.auth_init(authreq.to_urlencoded()) assert isinstance(res, dict) and "areq" in res @pytest.mark.parametrize("response_types", [ ['token id_token', 'id_token'], ['id_token token'], ['code id_token'], ['id_token code'] ]) def test_response_types_fail(self, response_types): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type='code') self.provider.cdb = { "client1": { "client_secret": "hemlighet", "redirect_uris": [("http://example.com/authz", None)], 'token_endpoint_auth_method': 'client_secret_post', 'response_types': response_types } } res = self.provider.auth_init(authreq.to_urlencoded()) assert isinstance(res, Response) _res = json.loads(res.message) assert _res['error'] == 'invalid_request'
def create_provider(self, session_db_factory): self.provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as')
class TestProvider(object): @pytest.fixture(autouse=True) def create_provider(self, session_db_factory): self.provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') def test_init(self, session_db_factory): provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client) assert provider provider = Provider("pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}) assert provider.urlmap["client1"] == ["https://example.com/authz"] def test_providerinfo(self): self.provider.baseurl = 'http://example.com/path1/path2' resp = self.provider.create_providerinfo() assert resp.to_dict( )['authorization_endpoint'] == 'http://example.com/path1/path2/authorization' def test_providerinfo_trailing(self): self.provider.baseurl = 'http://example.com/path1/path2/' resp = self.provider.create_providerinfo() assert resp.to_dict( )['authorization_endpoint'] == 'http://example.com/path1/path2/authorization' def test_verify_capabilities(self): capabilities = { 'grant_types_supported': ['authorization_code'], 'version': '3.0', 'response_types_supported': ['code', 'token'] } assert self.provider.verify_capabilities(capabilities) def test_verify_capabilities_mismatch_list(self): capabilities = { 'grant_types_supported': ['authorization_code'], 'response_types_supported': ['code token'] } # this is not supported assert not self.provider.verify_capabilities(capabilities) def test_verify_capabilities_mismatch_str(self): capabilities = { 'grant_types_supported': ['authorization_code'], 'version': '5.0' } # this is not matching assert not self.provider.verify_capabilities(capabilities) def test_verify_capabilities_missing(self): capabilities = { 'grant_types_supported': ['authorization_code'], 'str_value': 'test', # this is not supported 'we_dont_know_this': True } # this is not supported assert not self.provider.verify_capabilities(capabilities) def test_authorization_endpoint_faulty_redirect_uri(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087/authz", # faulty redirect uri "response_type": ["code"], "client_id": "a1b2c3" } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authorization_endpoint_wronge_response_mode(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://example.com", "response_type": ["code"], "response_mode": "fragment", "client_id": "a1b2c3" } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authorization_endpoint_faulty_redirect_uri_nwalker(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": " https://example.com.evil.com", # faulty redirect uri "response_type": ["code"], "client_id": "a1b2c3" } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authorization_endpoint_missing_client_id(self): # Url encoded request with missing client_id arq = 'scope=openid&state=id-6da9ca0cc23959f5f33e8becd9b08cae&' \ 'redirect_uri=+https%3A%2F%2Fexample.com&response_type=code' resp = self.provider.authorization_endpoint(request=arq) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authenticated(self): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") resp = self.provider.authorization_endpoint(urlparse(location).query) assert resp.status_code == 303 resp = urlparse(resp.message).query with LogCapture(level=logging.DEBUG) as logcap: aresp = cons.handle_authorization_response(query=resp) assert isinstance(aresp, AuthorizationResponse) assert _eq(aresp.keys(), ['state', 'code', 'client_id', 'iss']) assert _eq(cons.grant[sid].keys(), [ 'tokens', 'code', 'exp_in', 'seed', 'id_token', 'grant_expiration_time' ]) state = aresp['state'] assert _eq(logcap.records[0].msg, '- authorization - code flow -') assert verify_outcome(logcap.records[1].msg, 'QUERY: ', [ 'state={}'.format(state), 'code=<REDACTED>', 'client_id=client1', 'iss=https://example.com/as' ]) expected = { 'iss': 'https://example.com/as', 'state': state, 'code': '<REDACTED>', 'client_id': 'client1' } # Eval here to avoid intermittent failures due to dict ordering assert _eq(eval(logcap.records[2].msg[29:-1]), expected) expected = [ "'client_id': 'client1'", "'iss': 'https://example.com/as'", "'keyjar': <KeyJar(issuers=[])>" ] assert _eq(sorted(logcap.records[3].msg[22:-1].split(', ')), expected) def test_authenticated_token(self): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization", "token") QUERY_STRING = location.split("?")[1] resp = self.provider.authorization_endpoint(QUERY_STRING) auth_resp = parse_qs(urlparse(resp.message).fragment) assert "access_token" in auth_resp assert auth_resp["token_type"][0] == "Bearer" def test_token_endpoint(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id="client1", client_secret="hemlighet", grant_type='authorization_code') with LogCapture(level=logging.DEBUG) as logcap: resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = AccessTokenResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ['access_token', 'token_type', 'refresh_token']) expected = ( 'token_request: code=<REDACTED>&client_secret=<REDACTED>&grant_type=authorization_code' '&client_id=client1&redirect_uri=http%3A%2F%2Fexample.com%2Fauthz') assert _eq(parse_qs(logcap.records[1].msg[15:]), parse_qs(expected[15:])) expected = { u'code': '<REDACTED>', u'client_secret': '<REDACTED>', u'redirect_uri': u'http://example.com/authz', u'client_id': 'client1', u'grant_type': 'authorization_code' } # Don't try this at home, kids! # We have to eval() to a dict here because otherwise the arbitrary # ordering of the string causes the test to fail intermittently. assert _eq(eval(logcap.records[2].msg[4:]), expected) assert _eq(logcap.records[3].msg, 'Verified Client ID: client1') expected = { 'redirect_uri': u'http://example.com/authz', 'client_secret': '<REDACTED>', 'code': u'<REDACTED>', 'client_id': 'client1', 'grant_type': 'authorization_code' } assert eval(logcap.records[4].msg[20:]) == expected expected = { 'code': '<REDACTED>', 'authzreq': '', 'sub': 'sub', 'access_token': '<REDACTED>', 'token_type': 'Bearer', 'redirect_uri': 'http://example.com/authz', 'code_used': True, 'client_id': 'client1', 'oauth_state': 'token', 'refresh_token': '<REDACTED>', 'access_token_scope': '?' } assert _eq(eval(logcap.records[5].msg[7:]), expected) expected = { 'access_token': u'<REDACTED>', 'token_type': 'Bearer', 'refresh_token': '<REDACTED>' } assert _eq(eval(logcap.records[6].msg[21:]), expected) def test_token_endpoint_no_cache(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id="client1", client_secret="hemlighet", grant_type='authorization_code') resp = self.provider.token_endpoint(request=areq.to_urlencoded()) assert resp.headers == [('Pragma', 'no-cache'), ('Cache-Control', 'no-store'), ('Content-type', 'application/json')] def test_token_endpoint_unauth(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest(code=access_grant, redirect_uri="http://example.com/authz", client_id='<REDACTED>', client_secret="hemlighet", grant_type='authorization_code') resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = TokenErrorResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ['error_description', 'error']) def test_token_endpoint_malformed_code(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) _sdb[sid] = { "oauth_state": "authz", "authn_event": '', "authzreq": '', "client_id": 'client1', "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest(code=access_grant[0:len(access_grant) - 1], client_id='client1', redirect_uri="http://example.com/authz", client_secret='hemlighet', grant_type='authorization_code') txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr['error'] == "unauthorized_client" def test_token_endpoint_bad_redirect_uri(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) _sdb[sid] = { "oauth_state": "authz", "authn_event": '', "authzreq": '', "client_id": 'client1', "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest(code=access_grant, client_id='client1', redirect_uri="http://example.com/authz2", client_secret='hemlighet', grant_type='authorization_code') txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr['error'] == "unauthorized_client" 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_token_endpoint_bad_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) _sdb[sid] = { "oauth_state": "authz", "authn_event": '', "authzreq": '', "client_id": 'client1', "code": access_grant, 'state': 'state', "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # 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='other_state') txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr['error'] == "unauthorized_client" def test_token_endpoint_client_credentials(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", 'token_endpoint_auth_method': 'client_secret_basic', } areq = CCAccessTokenRequest(grant_type='client_credentials') authn = 'Basic Y2xpZW50Mjp2ZXJ5c2VjcmV0=' resp = self.provider.token_endpoint(request=areq.to_urlencoded(), authn=authn) parsed = TokenErrorResponse().from_json(resp.message) assert parsed['error'] == "unsupported_grant_type" def test_token_endpoint_password(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", 'token_endpoint_auth_method': 'client_secret_basic', } areq = ROPCAccessTokenRequest(grant_type='password', username='******', password='******') authn = 'Basic Y2xpZW50Mjp2ZXJ5c2VjcmV0=' resp = self.provider.token_endpoint(request=areq.to_urlencoded(), authn=authn) parsed = TokenErrorResponse().from_json(resp.message) assert parsed['error'] == "unsupported_grant_type" def test_token_endpoint_other(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", 'token_endpoint_auth_method': 'client_secret_basic', } areq = Message(grant_type='some_other') authn = 'Basic Y2xpZW50Mjp2ZXJ5c2VjcmV0=' with pytest.raises(UnSupported): self.provider.token_endpoint(request=areq.to_urlencoded(), authn=authn) def test_code_grant_type_used(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) _sdb[sid] = { "oauth_state": "authz", "authn_event": '', "authzreq": '', "client_id": 'client1', "code": access_grant, "code_used": True, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # 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') txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr['error'] == "invalid_grant" @pytest.mark.parametrize( "response_types", [['token id_token', 'id_token'], ['id_token token']]) def test_response_types(self, response_types): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type='id_token token') self.provider.cdb = { "client1": { "client_secret": "hemlighet", "redirect_uris": [("http://example.com/authz", None)], 'token_endpoint_auth_method': 'client_secret_post', 'response_types': response_types } } res = self.provider.auth_init(authreq.to_urlencoded()) assert isinstance(res, dict) and "areq" in res @pytest.mark.parametrize( "response_types", [['token id_token', 'id_token'], ['id_token token'], ['code id_token'], ['id_token code']]) def test_response_types_fail(self, response_types): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type='code') self.provider.cdb = { "client1": { "client_secret": "hemlighet", "redirect_uris": [("http://example.com/authz", None)], 'token_endpoint_auth_method': 'client_secret_post', 'response_types': response_types } } res = self.provider.auth_init(authreq.to_urlencoded()) assert isinstance(res, Response) _res = json.loads(res.message) assert _res['error'] == 'invalid_request' def test_complete_authz_no_cookie(self, session_db_factory): provider = Provider("pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER2, AUTHZ, verify_client, baseurl='https://example.com/as') areq = { 'client_id': 'client1', 'response_type': ['code'], 'redirect_uri': 'http://localhost:8087/authz' } sid = provider.sdb.access_token.key(user='******', areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { 'oauth_state': 'authz', 'sub': 'sub', 'client_id': 'client1', 'code': access_code, 'redirect_uri': 'http://localhost:8087/authz' } response, header, redirect, fragment = provider._complete_authz( 'sub', areq, sid) assert header == [] assert not fragment assert redirect == 'http://localhost:8087/authz' assert 'code' in response def test_complete_authz_cookie(self, session_db_factory): provider = Provider("pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') areq = { 'client_id': 'client1', 'response_type': ['code'], 'redirect_uri': 'http://localhost:8087/authz' } sid = provider.sdb.access_token.key(user='******', areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { 'oauth_state': 'authz', 'sub': 'sub', 'client_id': 'client1', 'code': access_code, 'redirect_uri': 'http://localhost:8087/authz' } response, header, redirect, fragment = provider._complete_authz( 'sub', areq, sid) assert len(header) == 1 cookie_header = header[0] assert cookie_header[0] == 'Set-Cookie' assert cookie_header[1].startswith('pyoidc_sso="sub][client1') assert not fragment assert redirect == 'http://localhost:8087/authz' assert 'code' in response def test_complete_authz_other_cookie_exists(self, session_db_factory): provider = Provider("pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') areq = { 'client_id': 'client1', 'response_type': ['code'], 'redirect_uri': 'http://localhost:8087/authz' } sid = provider.sdb.access_token.key(user='******', areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { 'oauth_state': 'authz', 'sub': 'sub', 'client_id': 'client1', 'code': access_code, 'redirect_uri': 'http://localhost:8087/authz' } cookie = 'Some-cookie=test::test' response, header, redirect, fragment = provider._complete_authz( 'sub', areq, sid, cookie=cookie) assert len(header) == 1 cookie_header = header[0] assert cookie_header[1].startswith('pyoidc_sso="sub][client1') assert not fragment assert redirect == 'http://localhost:8087/authz' assert 'code' in response def test_complete_authz_pyoidc_cookie_exists(self, session_db_factory): provider = Provider("pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl='https://example.com/as') areq = { 'client_id': 'client1', 'response_type': ['code'], 'redirect_uri': 'http://localhost:8087/authz' } sid = provider.sdb.access_token.key(user='******', areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { 'oauth_state': 'authz', 'sub': 'sub', 'client_id': 'client1', 'code': access_code, 'redirect_uri': 'http://localhost:8087/authz' } cookie = 'pyoidc_sso=test::test' response, header, redirect, fragment = provider._complete_authz( 'sub', areq, sid, cookie=cookie) assert len(header) == 0 assert not fragment assert redirect == 'http://localhost:8087/authz' assert 'code' in response
class TestProvider(object): @pytest.fixture(autouse=True) def create_provider(self, session_db_factory): self.provider = Provider( "pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl="https://example.com/as", ) def test_init(self, session_db_factory): provider = Provider( "pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, ) assert provider provider = Provider( "pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}, ) assert provider.urlmap["client1"] == ["https://example.com/authz"] def test_init_capabilities(self, session_db_factory): provider = Provider( "pyoicserv", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, capabilities={ "grant_types_supported": ["authorization_code"], "version": "1.0", "response_types_supported": ["code", "token"], }, ) assert provider assert provider.capabilities["version"] == "1.0" assert provider.capabilities["grant_types_supported"] == [ "authorization_code" ] def test_providerinfo(self): self.provider.baseurl = "http://example.com/path1/path2" resp = self.provider.create_providerinfo() assert (resp.to_dict()["authorization_endpoint"] == "http://example.com/path1/path2/authorization") def test_providerinfo_trailing(self): self.provider.baseurl = "http://example.com/path1/path2/" resp = self.provider.create_providerinfo() assert (resp.to_dict()["authorization_endpoint"] == "http://example.com/path1/path2/authorization") def test_verify_capabilities(self): capabilities = { "grant_types_supported": ["authorization_code"], "version": "3.0", "response_types_supported": ["code", "token"], } assert self.provider.verify_capabilities(capabilities) def test_verify_capabilities_mismatch_list(self): capabilities = { "grant_types_supported": ["authorization_code"], "response_types_supported": ["code token"], } # this is not supported assert not self.provider.verify_capabilities(capabilities) def test_verify_capabilities_mismatch_str(self): capabilities = { "grant_types_supported": ["authorization_code"], "version": "5.0", } # this is not matching assert not self.provider.verify_capabilities(capabilities) def test_verify_capabilities_missing(self): capabilities = { "grant_types_supported": ["authorization_code"], "str_value": "test", # this is not supported "we_dont_know_this": True, } # this is not supported assert not self.provider.verify_capabilities(capabilities) def test_authorization_endpoint_faulty_redirect_uri(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087/authz", # faulty redirect uri "response_type": ["code"], "client_id": "a1b2c3", } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authorization_endpoint_wronge_response_mode(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://example.com", "response_type": ["code"], "response_mode": "fragment", "client_id": "a1b2c3", } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authorization_endpoint_faulty_redirect_uri_nwalker(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": " https://example.com.evil.com", # faulty redirect uri "response_type": ["code"], "client_id": "a1b2c3", } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authorization_endpoint_missing_client_id(self): # Url encoded request with missing client_id arq = ("scope=openid&state=id-6da9ca0cc23959f5f33e8becd9b08cae&" "redirect_uri=+https%3A%2F%2Fexample.com&response_type=code") resp = self.provider.authorization_endpoint(request=arq) assert resp.status_code == 400 msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authenticated(self): _session_db = DictSessionBackend() cons = Consumer( _session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG, ) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") resp = self.provider.authorization_endpoint(urlparse(location).query) assert resp.status_code == 303 resp = urlparse(resp.message).query with LogCapture(level=logging.DEBUG) as logcap: aresp = cons.handle_authorization_response(query=resp) assert isinstance(aresp, AuthorizationResponse) assert _eq(aresp.keys(), ["state", "code", "client_id", "iss"]) assert _eq( cons.grant[sid].keys(), [ "tokens", "code", "exp_in", "seed", "id_token", "grant_expiration_time" ], ) state = aresp["state"] assert _eq(logcap.records[0].msg, "- authorization - code flow -") assert verify_outcome( logcap.records[1].msg, "QUERY: ", [ "state={}".format(state), "code=<REDACTED>", "client_id=client1", "iss=https://example.com/as", ], ) expected = { "iss": "https://example.com/as", "state": state, "code": "<REDACTED>", "client_id": "client1", } # Eval here to avoid intermittent failures due to dict ordering assert _eq(eval(logcap.records[2].msg[29:-1]), expected) expected2 = [ "'client_id': 'client1'", "'iss': 'https://example.com/as'", "'keyjar': <KeyJar(issuers=[])>", ] assert _eq(sorted(logcap.records[3].msg[22:-1].split(", ")), expected2) def test_authenticated_token(self): _session_db = DictSessionBackend() cons = Consumer( _session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG, ) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization", "token") QUERY_STRING = location.split("?")[1] resp = self.provider.authorization_endpoint(QUERY_STRING) auth_resp = parse_qs(urlparse(resp.message).fragment) assert "access_token" in auth_resp assert auth_resp["token_type"][0] == "Bearer" def test_token_endpoint(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest( code=access_grant, redirect_uri="http://example.com/authz", client_id="client1", client_secret="hemlighet", grant_type="authorization_code", ) with LogCapture(level=logging.DEBUG) as logcap: resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = AccessTokenResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ["access_token", "token_type", "refresh_token"]) expected = ( "token_request: code=<REDACTED>&client_secret=<REDACTED>&grant_type=authorization_code" "&client_id=client1&redirect_uri=http%3A%2F%2Fexample.com%2Fauthz") assert _eq(parse_qs(logcap.records[1].msg[15:]), parse_qs(expected[15:])) expected2 = { "code": "<REDACTED>", "client_secret": "<REDACTED>", "redirect_uri": "http://example.com/authz", "client_id": "client1", "grant_type": "authorization_code", } # Don't try this at home, kids! # We have to eval() to a dict here because otherwise the arbitrary # ordering of the string causes the test to fail intermittently. assert _eq(eval(logcap.records[2].msg[4:]), expected2) assert _eq(logcap.records[3].msg, "Verified Client ID: client1") expected3 = { "redirect_uri": "http://example.com/authz", "client_secret": "<REDACTED>", "code": "<REDACTED>", "client_id": "client1", "grant_type": "authorization_code", } assert eval(logcap.records[4].msg[20:]) == expected3 expected4 = { "code": "<REDACTED>", "authzreq": "", "sub": "sub", "access_token": "<REDACTED>", "token_type": "Bearer", "redirect_uri": "http://example.com/authz", "code_used": True, "client_id": "client1", "oauth_state": "token", "refresh_token": "<REDACTED>", "access_token_scope": "?", } assert _eq(eval(logcap.records[5].msg[7:]), expected4) expected5 = { "access_token": "<REDACTED>", "token_type": "Bearer", "refresh_token": "<REDACTED>", } assert _eq(eval(logcap.records[6].msg[21:]), expected5) def test_token_endpoint_no_cache(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest( code=access_grant, redirect_uri="http://example.com/authz", client_id="client1", client_secret="hemlighet", grant_type="authorization_code", ) resp = self.provider.token_endpoint(request=areq.to_urlencoded()) assert resp.headers == [ ("Pragma", "no-cache"), ("Cache-Control", "no-store"), ("Content-type", "application/json"), ] def test_token_endpoint_unauth(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest( code=access_grant, redirect_uri="http://example.com/authz", client_id="<REDACTED>", client_secret="hemlighet", grant_type="authorization_code", ) resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = TokenErrorResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ["error_description", "error"]) def test_token_endpoint_malformed_code(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) _sdb[sid] = { "oauth_state": "authz", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest( code=access_grant[0:len(access_grant) - 1], client_id="client1", redirect_uri="http://example.com/authz", client_secret="hemlighet", grant_type="authorization_code", ) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr["error"] == "unauthorized_client" def test_token_endpoint_bad_redirect_uri(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) _sdb[sid] = { "oauth_state": "authz", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # Construct Access token request areq = AccessTokenRequest( code=access_grant, client_id="client1", redirect_uri="http://example.com/authz2", client_secret="hemlighet", grant_type="authorization_code", ) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr["error"] == "unauthorized_client" 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_token_endpoint_bad_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) _sdb[sid] = { "oauth_state": "authz", "authzreq": "", "client_id": "client1", "code": access_grant, "state": "state", "code_used": False, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # 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="other_state", ) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr["error"] == "unauthorized_client" def test_token_endpoint_client_credentials(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", "token_endpoint_auth_method": "client_secret_basic", } areq = CCAccessTokenRequest(grant_type="client_credentials") authn = "Basic Y2xpZW50Mjp2ZXJ5c2VjcmV0=" resp = self.provider.token_endpoint(request=areq.to_urlencoded(), authn=authn) parsed = TokenErrorResponse().from_json(resp.message) assert parsed["error"] == "unsupported_grant_type" def test_token_endpoint_password(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", "token_endpoint_auth_method": "client_secret_basic", } areq = ROPCAccessTokenRequest(grant_type="password", username="******", password="******") authn = "Basic Y2xpZW50Mjp2ZXJ5c2VjcmV0=" resp = self.provider.token_endpoint(request=areq.to_urlencoded(), authn=authn) parsed = TokenErrorResponse().from_json(resp.message) assert parsed["error"] == "unsupported_grant_type" def test_token_endpoint_other(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.access_token.key(user="******", areq=authreq) access_grant = _sdb.access_token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz", "token_endpoint_auth_method": "client_secret_basic", } areq = Message(grant_type="some_other") authn = "Basic Y2xpZW50Mjp2ZXJ5c2VjcmV0=" with pytest.raises(UnSupported): self.provider.token_endpoint(request=areq.to_urlencoded(), authn=authn) def test_code_grant_type_used(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) _sdb[sid] = { "oauth_state": "authz", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": True, "scope": ["openid"], "redirect_uri": "http://example.com/authz", } # 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", ) txt = areq.to_urlencoded() resp = self.provider.token_endpoint(request=txt) atr = TokenErrorResponse().deserialize(resp.message, "json") assert atr["error"] == "invalid_grant" @pytest.mark.parametrize( "response_types", [["token id_token", "id_token"], ["id_token token"]]) def test_response_types(self, response_types): authreq = AuthorizationRequest( state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type="id_token token", ) self.provider.cdb = { "client1": { "client_secret": "hemlighet", "redirect_uris": [("http://example.com/authz", None)], "token_endpoint_auth_method": "client_secret_post", "response_types": response_types, } } res = self.provider.auth_init(authreq.to_urlencoded()) assert isinstance(res, dict) and "areq" in res @pytest.mark.parametrize( "response_types", [ ["token id_token", "id_token"], ["id_token token"], ["code id_token"], ["id_token code"], ], ) def test_response_types_fail(self, response_types): authreq = AuthorizationRequest( state="state", redirect_uri="http://example.com/authz", client_id="client1", response_type="code", ) self.provider.cdb = { "client1": { "client_secret": "hemlighet", "redirect_uris": [("http://example.com/authz", None)], "token_endpoint_auth_method": "client_secret_post", "response_types": response_types, } } res = self.provider.auth_init(authreq.to_urlencoded()) assert isinstance(res, Response) _res = json.loads(res.message) assert _res["error"] == "invalid_request" def test_complete_authz_no_cookie(self, session_db_factory): provider = Provider( "pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER2, AUTHZ, verify_client, baseurl="https://example.com/as", ) areq = { "client_id": "client1", "response_type": ["code"], "redirect_uri": "http://localhost:8087/authz", } sid = provider.sdb.access_token.key(user="******", areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { "oauth_state": "authz", "sub": "sub", "client_id": "client1", "code": access_code, "redirect_uri": "http://localhost:8087/authz", } response, header, redirect, fragment = provider._complete_authz( "sub", areq, sid) assert header == [] assert not fragment assert redirect == "http://localhost:8087/authz" assert "code" in response def test_complete_authz_cookie(self, session_db_factory): provider = Provider( "pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl="https://example.com/as", ) areq = { "client_id": "client1", "response_type": ["code"], "redirect_uri": "http://localhost:8087/authz", } sid = provider.sdb.access_token.key(user="******", areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { "oauth_state": "authz", "sub": "sub", "client_id": "client1", "code": access_code, "redirect_uri": "http://localhost:8087/authz", } response, header, redirect, fragment = provider._complete_authz( "sub", areq, sid) assert len(header) == 1 cookie_header = header[0] assert cookie_header[0] == "Set-Cookie" assert cookie_header[1].startswith('pyoidc_sso="sub][client1') assert not fragment assert redirect == "http://localhost:8087/authz" assert "code" in response def test_complete_authz_other_cookie_exists(self, session_db_factory): provider = Provider( "pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl="https://example.com/as", ) areq = { "client_id": "client1", "response_type": ["code"], "redirect_uri": "http://localhost:8087/authz", } sid = provider.sdb.access_token.key(user="******", areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { "oauth_state": "authz", "sub": "sub", "client_id": "client1", "code": access_code, "redirect_uri": "http://localhost:8087/authz", } cookie = "Some-cookie=test::test" response, header, redirect, fragment = provider._complete_authz( "sub", areq, sid, cookie=cookie) assert len(header) == 1 cookie_header = header[0] assert cookie_header[1].startswith('pyoidc_sso="sub][client1') assert not fragment assert redirect == "http://localhost:8087/authz" assert "code" in response def test_complete_authz_pyoidc_cookie_exists(self, session_db_factory): provider = Provider( "pyoicserver", session_db_factory(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, baseurl="https://example.com/as", ) areq = { "client_id": "client1", "response_type": ["code"], "redirect_uri": "http://localhost:8087/authz", } sid = provider.sdb.access_token.key(user="******", areq=areq) access_code = provider.sdb.access_token(sid=sid) provider.sdb[sid] = { "oauth_state": "authz", "sub": "sub", "client_id": "client1", "code": access_code, "redirect_uri": "http://localhost:8087/authz", } cookie = "pyoidc_sso=test::test" response, header, redirect, fragment = provider._complete_authz( "sub", areq, sid, cookie=cookie) assert len(header) == 0 assert not fragment assert redirect == "http://localhost:8087/authz" assert "code" in response
authn = CasAuthnMethod( None, config.CAS_SERVER, config.SERVICE_URL, "%s/authorization" % config.issuer, UserLDAPMemberValidation(**config.LDAP_EXTRAVALIDATION), ) else: from oic.utils.authn.user import UsernamePasswordMako authn = UsernamePasswordMako(None, "login.mako", LOOKUP, PASSWD, "%s/authorization" % config.issuer) # dealing with authorization authz = AuthzHandling() # User info database OAS = Provider(config.issuer, SessionDB(), cdb, authn, authz, verify_client, config.SYM_KEY) authn.srv = OAS try: OAS.cookie_ttl = config.COOKIETTL except AttributeError: pass try: OAS.cookie_name = config.COOKIENAME except AttributeError: pass OAS.cookie_func = http_util.make_cookie # print URLS
for cnf in config.AUTHN_METHOD.values(): try: cnf["config"]["return_to"] = cnf["config"]["return_to"] % args.port except KeyError: pass # Initiate the authentication broker. This is the service that # chooses which authentication method that is to be used. broker = authn_setup(config) # dealing with authorization, this is just everything goes. authz = Implicit() # Initiate the OAuth2 provider instance OAS = Provider(config.issuer, SessionDB(), cdb, broker, authz, client_authn=verify_client, symkey=config.SYM_KEY) # set some parameters try: OAS.cookie_ttl = config.COOKIETTL except AttributeError: pass try: OAS.cookie_name = config.COOKIENAME except AttributeError: pass if args.debug: LOGGER.setLevel(logging.DEBUG) OAS.debug = True
def create_provider(self): self.provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client)
class TestProvider(object): @pytest.fixture(autouse=True) def create_provider(self): self.provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client) def test_init(self): provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client) assert provider provider = Provider("pyoicserv", sdb.SessionDB(ISSUER), CDB, AUTHN_BROKER, AUTHZ, verify_client, urlmap={"client1": ["https://example.com/authz"]}) assert provider.urlmap["client1"] == ["https://example.com/authz"] def test_authorization_endpoint_faulty_redirect_uri(self): bib = { "scope": ["openid"], "state": "id-6da9ca0cc23959f5f33e8becd9b08cae", "redirect_uri": "http://localhost:8087/authz", # faulty redirect uri "response_type": ["code"], "client_id": "a1b2c3" } arq = AuthorizationRequest(**bib) resp = self.provider.authorization_endpoint( request=arq.to_urlencoded()) assert resp.status == "400 Bad Request" msg = json.loads(resp.message) assert msg["error"] == "invalid_request" def test_authenticated(self): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") resp = self.provider.authorization_endpoint(urlparse(location).query) assert resp.status == "302 Found" resp = urlparse(resp.message).query aresp = cons.handle_authorization_response(query=resp) assert isinstance(aresp, AuthorizationResponse) assert _eq(aresp.keys(), ['state', 'code']) assert _eq(cons.grant[sid].keys(), [ 'tokens', 'code', 'exp_in', 'seed', 'id_token', 'grant_expiration_time' ]) def test_authenticated_token(self): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid, location = cons.begin("http://localhost:8087", "http://localhost:8088/authorization", "token") QUERY_STRING = location.split("?")[1] resp = self.provider.authorization_endpoint(QUERY_STRING) auth_resp = parse_qs(urlparse(resp.message).fragment) assert "access_token" in auth_resp assert auth_resp["token_type"][0] == "Bearer" def test_token_endpoint(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest( code=access_grant, redirect_uri="http://example.com/authz", client_id="client1", client_secret="hemlighet", ) resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = AccessTokenResponse().deserialize(resp.message, "json") assert _eq( atr.keys(), ['access_token', 'expires_in', 'token_type', 'refresh_token']) def test_token_endpoint_unauth(self): authreq = AuthorizationRequest(state="state", redirect_uri="http://example.com/authz", client_id="client1") _sdb = self.provider.sdb sid = _sdb.token.key(user="******", areq=authreq) access_grant = _sdb.token(sid=sid) _sdb[sid] = { "oauth_state": "authz", "sub": "sub", "authzreq": "", "client_id": "client1", "code": access_grant, "code_used": False, "redirect_uri": "http://example.com/authz" } # Construct Access token request areq = AccessTokenRequest( code=access_grant, redirect_uri="http://example.com/authz", client_id="client2", client_secret="hemlighet", ) resp = self.provider.token_endpoint(request=areq.to_urlencoded()) atr = TokenErrorResponse().deserialize(resp.message, "json") assert _eq(atr.keys(), ['error_description', 'error'])