def test_init(self): cons = Consumer({}, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons._backup("123456") assert "123456" in cons.sdb cons = Consumer({}, client_config=CLIENT_CONFIG, **CONSUMER_CONFIG) assert cons.authorization_endpoint is None cons = Consumer({}, **CONSUMER_CONFIG) assert cons.authorization_endpoint is None
def test_factory(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) sid = stateID("https://example.org/", cons.seed) cons.state = sid cons._backup(sid) cons.sdb["seed:%s" % cons.seed] = sid kaka = make_cookie(CLIENT_CONFIG["client_id"], cons.state, cons.seed, expire=360, path="/") _oac = factory(kaka[1], _session_db, CLIENT_CONFIG["client_id"], client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) assert _oac assert _oac.state == cons.state assert _oac.seed == cons.seed
def __init__(self, outgoing, internal_attributes, config, base_url, name, external_type, user_id_attr): """ :param outgoing: Callback should be called by the module after the authorization in the backend is done. :param internal_attributes: Mapping dictionary between SATOSA internal attribute names and the names returned by underlying IdP's/OP's as well as what attributes the calling SP's and RP's expects namevice. :param config: Configuration parameters for the module. :param base_url: base url of the service :param name: name of the plugin :param external_type: The name for this module in the internal attributes. :type outgoing: (satosa.context.Context, satosa.internal.InternalData) -> satosa.response.Response :type internal_attributes: dict[string, dict[str, str | list[str]]] :type config: dict[str, dict[str, str] | list[str]] :type base_url: str :type name: str :type external_type: str """ super().__init__(outgoing, internal_attributes, base_url, name) self.config = config self.redirect_url = "%s/%s" % (self.config["base_url"], self.config["authz_page"]) self.external_type = external_type self.user_id_attr = user_id_attr self.consumer = Consumer(session_db=None, client_config=self.config["client_config"], server_info=self.config["server_info"], authz_page=self.config["authz_page"], response_type=self.config["response_type"]) self.consumer.client_secret = self.config["client_secret"]
def test_consumer_parse_access_token(): # implicit flow test _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True environ = BASE_ENVIRON cons.response_type = ["token"] _ = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") atr = AccessTokenResponse(access_token="2YotnFZFEjr1zCsicMWpAA", token_type="example", refresh_token="tGzv3JOkF0XG5Qx2TlKWIA", example_parameter="example_value", state=cons.state) res = cons.handle_authorization_response(query=atr.to_urlencoded()) assert res.type() == "AccessTokenResponse" print cons.grant[cons.state] grant = cons.grant[cons.state] assert len(grant.tokens) == 1 token = grant.tokens[0] assert token.access_token == "2YotnFZFEjr1zCsicMWpAA"
def test_consumer_client_get_access_token_reques(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.client_secret = "secret0" cons.state = "state" cons.redirect_uris = ["https://www.example.com/oic/cb"] resp1 = AuthorizationResponse(code="auth_grant", state="state") cons.parse_response(AuthorizationResponse, resp1.to_urlencoded(), "urlencoded") resp2 = AccessTokenResponse(access_token="token1", token_type="Bearer", expires_in=0, state="state") cons.parse_response(AccessTokenResponse, resp2.to_urlencoded(), "urlencoded") url, body, http_args = cons.get_access_token_request() assert url == "http://localhost:8088/token" print body assert body == ("code=auth_grant&client_secret=secret0&" "grant_type=authorization_code&client_id=number5&" "redirect_uri=https%3A%2F%2Fwww.example.com%2Foic%2Fcb") assert http_args == { 'headers': { 'Content-type': 'application/x-www-form-urlencoded' } }
def test_consumer_client_get_access_token_reques(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.client_secret = "secret0" _state = "state" cons.redirect_uris = ["https://www.example.com/oic/cb"] resp1 = AuthorizationResponse(code="auth_grant", state=_state) cons.parse_response(AuthorizationResponse, resp1.to_urlencoded(), "urlencoded") resp2 = AccessTokenResponse(access_token="token1", token_type="Bearer", expires_in=0, state=_state) cons.parse_response(AccessTokenResponse, resp2.to_urlencoded(), "urlencoded") url, body, http_args = cons.get_access_token_request(_state) url_obj = URLObject.create(url) expected_url_obj = URLObject.create("http://localhost:8088/token") assert url_obj == expected_url_obj body_splits = body.split('&') expected_body_splits = "code=auth_grant&client_secret=secret0&" \ "grant_type=authorization_code&client_id=number5&" \ "redirect_uri=https%3A%2F%2Fwww.example.com%2Foic%2Fcb".split('&') assert set(body_splits) == set(expected_body_splits) assert http_args == { 'headers': { 'Content-type': 'application/x-www-form-urlencoded' } }
def test_provider_authenticated_token(): 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", "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_factory(): sdb = DictSessionBackend() consumer = Consumer( sdb, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, settings=CLIENT_SETTINGS, **CONSUMER_CONFIG, ) sid = stateID("https://example.org/", consumer.seed) _state = sid consumer._backup(sid) consumer.sdb["seed:%s" % consumer.seed] = sid kaka = make_cookie(CLIENT_CONFIG["client_id"], _state, consumer.seed, expire=360, path="/") _oac = factory( kaka[1], sdb, CLIENT_CONFIG["client_id"], client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG, ) assert _oac.client_id == consumer.client_id assert _oac.seed == consumer.seed
def create_consumer(self): self.consumer = Consumer( DictSessionBackend(), client_config=CLIENT_CONFIG, server_info=SERVER_INFO, settings=CLIENT_SETTINGS, **CONSUMER_CONFIG, )
def test_provider_config(self): c = Consumer(None, None) response = ASConfigurationResponse(**{'issuer': 'https://example.com', 'end_session_endpoint': 'https://example.com/end_session'}) with responses.RequestsMock() as rsps: rsps.add(responses.GET, 'https://example.com/.well-known/openid-configuration', json=response.to_dict()) info = c.provider_config('https://example.com') assert isinstance(info, ASConfigurationResponse) assert _eq(info.keys(), ['issuer', 'version', 'end_session_endpoint']) assert info["end_session_endpoint"] == "https://example.com/end_session"
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_consumer_client_auth_info(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.client_secret = "secret0" ra, ha, extra = cons.client_auth_info() assert ra == {'client_secret': 'secret0', 'client_id': 'number5'} assert ha == {} assert extra == {'auth_method': 'bearer_body'}
def test_init(self): cons = Consumer( DictSessionBackend(), client_config=CLIENT_CONFIG, server_info=SERVER_INFO, settings=CLIENT_SETTINGS, **CONSUMER_CONFIG, ) cons._backup("123456") assert "123456" in cons.sdb cons = Consumer( DictSessionBackend(), client_config=CLIENT_CONFIG, settings=CLIENT_SETTINGS, **CONSUMER_CONFIG, ) assert cons.authorization_endpoint is None cons = Consumer(DictSessionBackend, **CONSUMER_CONFIG) assert cons.authorization_endpoint is None
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_consumer_parse_authz_error_2(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True _ = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") atr = TokenErrorResponse(error="invalid_client") QUERY_STRING = atr.to_urlencoded() raises(AuthzError, "cons.handle_authorization_response(query=QUERY_STRING)")
def test_provider_config(self): c = Consumer(None, None) response = ASConfigurationResponse( **{ "issuer": "https://example.com", "end_session_endpoint": "https://example.com/end_session", }) with responses.RequestsMock() as rsps: rsps.add( responses.GET, "https://example.com/.well-known/openid-configuration", json=response.to_dict(), ) info = c.provider_config("https://example.com") assert isinstance(info, ASConfigurationResponse) assert _eq(info.keys(), ["issuer", "version", "end_session_endpoint"]) assert info[ "end_session_endpoint"] == "https://example.com/end_session"
def get_consumer(self): """ Creates a OAuth 2.0 consumer from a given configuration. :param user_id_hash_type: Tells the OAuth consumer how to ask for user id. In oidc can pairwise and public be used. :type user_id_hash_type: UserIdHashType :rtype: Consumer :return: An OAuth 2.0 consumer. """ consumer = Consumer(session_db=None, client_config=self.config["client_config"], server_info=self.config["server_info"], authz_page=self.config["authz_page"], response_type=self.config["response_type"]) consumer.client_secret = self.config["client_secret"] return consumer
def test_consumer_handle_authorization_response(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True sid, loc = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") atr = AuthorizationResponse(code="SplxlOBeZQQYbYS6WxSbIA", state=sid) res = cons.handle_authorization_response(query=atr.to_urlencoded()) assert res.type() == "AuthorizationResponse" print cons.grant[sid] grant = cons.grant[sid] assert grant.code == "SplxlOBeZQQYbYS6WxSbIA"
def test_consumer_parse_authz_exception(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) cons.debug = True sid, loc = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") atr = AuthorizationResponse(code="SplxlOBeZQQYbYS6WxSbIA", state=sid) adict = atr.to_dict() del adict["code"] QUERY_STRING = urllib.urlencode(adict) raises(MissingRequiredAttribute, "cons.handle_authorization_response(query=QUERY_STRING)")
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(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_consumer_begin(): _session_db = {} cons = Consumer(_session_db, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG) loc = cons.begin("http://localhost:8087", "http://localhost:8088/authorization") # state is dynamic params = { "scope": "openid", "state": cons.state, "redirect_uri": "http://localhost:8087/authz", "response_type": "code", "client_id": "number5" } url = "http://localhost:8088/authorization?%s" % urllib.urlencode(params) assert loc == url
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 create_consumer(self): self.consumer = Consumer({}, client_config=CLIENT_CONFIG, server_info=SERVER_INFO, **CONSUMER_CONFIG)
# is run. sys.path.insert(0, ".") # If a specific configuration directory is specified look there first if args.conf_path: sys.path.insert(0, args.conf_path) RP_CONF = importlib.import_module(args.config) # per AS instantiate a consumer for name, info in RP_CONF.AS_CONF.items(): c_conf = {"client_id": info["client_id"]} CONSUMER[name] = Consumer(session_db={}, client_config=c_conf, server_info={ "authorization_endpoint": info["authorization_endpoint"], "token_endpoint": info["token_endpoint"] }, authz_page="authz_cb", response_type="code") CONSUMER[name].client_secret = info["client_secret"] SRV = wsgiserver.CherryPyWSGIServer( ('0.0.0.0', RP_CONF.PORT), SessionMiddleware(application, session_opts)) if RP_CONF.BASE.startswith("https"): from cherrypy.wsgiserver import ssl_pyopenssl SRV.ssl_adapter = ssl_pyopenssl.pyOpenSSLAdapter(