From b9e18b6bcf0fb3d981b68671d856a0f3bb9dd31e Mon Sep 17 00:00:00 2001 From: "alejandro.nieto" Date: Tue, 15 Feb 2022 14:05:39 +0100 Subject: [PATCH 1/6] Some documentation --- oidc_example/simple_op/src/provider/server/server.py | 3 +++ src/oic/oic/provider.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/oidc_example/simple_op/src/provider/server/server.py b/oidc_example/simple_op/src/provider/server/server.py index e01917957..6d1c9cbba 100644 --- a/oidc_example/simple_op/src/provider/server/server.py +++ b/oidc_example/simple_op/src/provider/server/server.py @@ -112,8 +112,11 @@ def setup_authentication_methods(authn_config, template_env): routing = {} ac = AuthnBroker() for authn_method in authn_config: + + # Create instance of each auth class cls = make_cls_from_name(authn_method["class"]) instance = cls(template_env=template_env, **authn_method["kwargs"]) + ac.add(authn_method["acr"], instance) routing[instance.url_endpoint] = VerifierMiddleware(instance) diff --git a/src/oic/oic/provider.py b/src/oic/oic/provider.py index b8bdc4d25..42378afc3 100644 --- a/src/oic/oic/provider.py +++ b/src/oic/oic/provider.py @@ -255,6 +255,9 @@ def __init__( logout_path="", settings: PyoidcSettings = None, ): + """ + :param name the iss, which is the URI of the OP. + """ self.settings = settings or OicProviderSettings() if verify_ssl is not None: warnings.warn( From e22e2284bb2af1a8c0ad154f4d2a31c5d9cdac3a Mon Sep 17 00:00:00 2001 From: "alejandro.nieto" Date: Thu, 17 Feb 2022 14:23:12 +0100 Subject: [PATCH 2/6] More docs --- .../simple_op/src/provider/authn/user_pass.py | 5 +++++ .../simple_op/src/provider/server/server.py | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/oidc_example/simple_op/src/provider/authn/user_pass.py b/oidc_example/simple_op/src/provider/authn/user_pass.py index 65decd4ad..46695f7f1 100644 --- a/oidc_example/simple_op/src/provider/authn/user_pass.py +++ b/oidc_example/simple_op/src/provider/authn/user_pass.py @@ -29,6 +29,11 @@ def __call__(self, *args, **kwargs): state=json.dumps(kwargs), **self.kwargs)) + """ + Checks if the user can be authenticated with the password provided + + :param kwargs: + """ def verify(self, *args, **kwargs): username = kwargs["username"] if username in self.user_db and self.user_db[username] == kwargs[ diff --git a/oidc_example/simple_op/src/provider/server/server.py b/oidc_example/simple_op/src/provider/server/server.py index 6d1c9cbba..07e52f233 100644 --- a/oidc_example/simple_op/src/provider/server/server.py +++ b/oidc_example/simple_op/src/provider/server/server.py @@ -107,17 +107,24 @@ def resp2flask(resp): return resp.message, resp.status, resp.headers +""" +Creates an AuthnBroker with the authentication methods set in settings.yaml. + +:returns an AuthnBroker and the routing. +""" def setup_authentication_methods(authn_config, template_env): """Add all authentication methods specified in the configuration.""" routing = {} ac = AuthnBroker() for authn_method in authn_config: - # Create instance of each auth class + # Create instance of the appropiate auth class. cls = make_cls_from_name(authn_method["class"]) instance = cls(template_env=template_env, **authn_method["kwargs"]) + # Adds the auth method name to the broker. ac.add(authn_method["acr"], instance) + routing[instance.url_endpoint] = VerifierMiddleware(instance) return ac, routing @@ -126,6 +133,8 @@ def setup_authentication_methods(authn_config, template_env): def setup_endpoints(provider): """Setup the OpenID Connect Provider endpoints.""" app_routing = {} + + # Each provider.***** is a pointer to a function endpoints = [ AuthorizationEndpoint( pyoidcMiddleware(provider.authorization_endpoint)), @@ -207,6 +216,8 @@ def main(): client_db = {} session_db = create_session_db(issuer, secret=rndstr(32), password=rndstr(32)) + + # verify_client is a pointer to that function which is used in the token endpoint. provider = Provider(issuer, session_db, client_db, authn_broker, userinfo, AuthzHandling(), verify_client, None) provider.baseurl = issuer From 0cd29446a83793ba6677c76e95f1ec8ab10a2a35 Mon Sep 17 00:00:00 2001 From: "alejandro.nieto" Date: Thu, 17 Mar 2022 12:10:01 +0100 Subject: [PATCH 3/6] Fix to make the authentication request/response work. --- oidc_example/simple_op/src/provider/server/server.py | 8 +++++--- src/oic/oauth2/__init__.py | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/oidc_example/simple_op/src/provider/server/server.py b/oidc_example/simple_op/src/provider/server/server.py index 07e52f233..463ec3926 100644 --- a/oidc_example/simple_op/src/provider/server/server.py +++ b/oidc_example/simple_op/src/provider/server/server.py @@ -7,7 +7,6 @@ from functools import partial from functools import wraps from urllib import parse as urlparse - import cherrypy import yaml from cherrypy import wsgiserver @@ -70,13 +69,16 @@ def wrapper(environ, start_response): url = "{base_url}?{query_string}".format( base_url="/authorization", - query_string=kwargs["state"]["query"]) + query_string=urlparse.urlparse(environ.get("HTTP_REFERER")).query) response = SeeOther(url, headers=[(set_cookie, cookie_value)]) return response(environ, start_response) + else: # Unsuccessful authentication url = "{base_url}?{query_string}".format( base_url="/authorization", - query_string=kwargs["state"]["query"]) + query_string=urlparse.urlparse(environ.get("HTTP_REFERER")).query) + response = SeeOther(url, headers=[(set_cookie, cookie_value)]) + return response(environ, start_response) response = SeeOther(url) return response(environ, start_response) diff --git a/src/oic/oauth2/__init__.py b/src/oic/oauth2/__init__.py index fbd5a94b4..61d895848 100644 --- a/src/oic/oauth2/__init__.py +++ b/src/oic/oauth2/__init__.py @@ -425,6 +425,8 @@ def construct_AuthorizationRequest( else: request_args = {} + request_args.update(kwargs) + if "client_id" not in request_args: request_args["client_id"] = self.client_id elif not request_args["client_id"]: From 897a6527de0b41d9a313aa93c8b5affe64640b24 Mon Sep 17 00:00:00 2001 From: "alejandro.nieto" Date: Thu, 17 Mar 2022 12:21:52 +0100 Subject: [PATCH 4/6] Fix to make token request/response and userinfo request/response work. --- oidc_example/simple_rp/src/rp.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/oidc_example/simple_rp/src/rp.py b/oidc_example/simple_rp/src/rp.py index 66d33fc33..b464381d4 100644 --- a/oidc_example/simple_rp/src/rp.py +++ b/oidc_example/simple_rp/src/rp.py @@ -98,6 +98,8 @@ def authenticate(self, uid): ] _, keyjar, _ = build_keyjar(keys) cherrypy.session["client"] = Client(verify_ssl=self.verify_ssl, keyjar=keyjar) + cherrypy.session["client"].token_endpoint = "https://localhost/token" + cherrypy.session["client"].userinfo_endpoint = "https://localhost/userinfo" # webfinger+registration self.rp.register_with_dynamic_provider(cherrypy.session, uid) From 1e98232734050c3150dcc1041b963c43a024393c Mon Sep 17 00:00:00 2001 From: "alejandro.nieto" Date: Thu, 17 Mar 2022 12:34:37 +0100 Subject: [PATCH 5/6] Fixed error to make the id token verification work. --- src/oic/oic/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oic/oic/message.py b/src/oic/oic/message.py index c719488f0..a6e901906 100644 --- a/src/oic/oic/message.py +++ b/src/oic/oic/message.py @@ -298,7 +298,7 @@ def verify_id_token(instance, check_hash=False, **kwargs): if "keyjar" in kwargs: try: - if _body["iss"] not in kwargs["keyjar"]: + if _body["iss"] not in kwargs["iss"]: raise ValueError("Unknown issuer") except KeyError: raise MissingRequiredAttribute("iss") From ce469a9832015fdd9b151b1d0aa6686998b8b41c Mon Sep 17 00:00:00 2001 From: "alejandro.nieto" Date: Thu, 17 Mar 2022 12:47:30 +0100 Subject: [PATCH 6/6] Another fix related to the token request/response --- oidc_example/simple_op/src/provider/server/server.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/oidc_example/simple_op/src/provider/server/server.py b/oidc_example/simple_op/src/provider/server/server.py index 463ec3926..08cf7c4fe 100644 --- a/oidc_example/simple_op/src/provider/server/server.py +++ b/oidc_example/simple_op/src/provider/server/server.py @@ -95,7 +95,11 @@ def pyoidcMiddleware(func): def wrapper(environ, start_response): data = get_or_post(environ) cookies = environ.get("HTTP_COOKIE", "") - resp = func(request=data, cookie=cookies) + if(environ.get("REQUEST_URI", "") == "/token"): + # This is correct at least for our case which is the authorization code flow. + resp = func(request=data, cookie=cookies, authn=environ.get("HTTP_AUTHORIZATION", "")) + else: + resp = func(request=data, cookie=cookies) return resp(environ, start_response) return wrapper