From fbb190b455f2d21a194bf83eb985697b5f723215 Mon Sep 17 00:00:00 2001 From: Jonathan Perret Date: Thu, 18 Sep 2025 15:29:10 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB(oidc-test-cli?= =?UTF-8?q?ent)=20configure=20OIDC=20client=20on=20each=20request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Downloading the discovery document from the OIDC provider on each request rather than on startup lets the oidc-test-client be independent of the availability of the OIDC provider, which is useful in development scenarios. --- docker-compose.yml | 5 ---- docker/oidc-test-client/app.py | 47 ++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 2fd9ed2..f4bea66 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,19 +44,14 @@ services: oidc-test-client: build: docker/oidc-test-client - depends_on: - - nginx # nginx must be up to override satosa.traefik.me resolution - - app-dev stop_signal: SIGKILL volumes: - ./docker/oidc-test-client:/app - ./env.d/development/certs/mkcert-root-ca.pem:/usr/local/share/ca-certificates/mkcert-root-ca.crt # - run update-ca-certificates to make mkcert certificates valid - # - add startup delay because IDP must be available on boot entrypoint: | /bin/bash -c ' cat /usr/local/share/ca-certificates/mkcert-root-ca.crt >> $(python -m certifi) - sleep 1 cd /app exec python app.py ' diff --git a/docker/oidc-test-client/app.py b/docker/oidc-test-client/app.py index d6ac74c..73e6f1e 100644 --- a/docker/oidc-test-client/app.py +++ b/docker/oidc-test-client/app.py @@ -5,6 +5,7 @@ from oic import rndstr from oic.oic.message import Claims, ClaimsRequest, RegistrationResponse from oic.utils.http_util import Redirect from oic.oic.message import AuthorizationResponse +from werkzeug.exceptions import InternalServerError import secrets import logging import os @@ -23,21 +24,27 @@ app.config.update( } ) -client = Client(client_authn_method=CLIENT_AUTHN_METHOD) -provider_info = client.provider_config(os.environ["OIDC_PROVIDER"]) +def create_client() -> Client: + client = Client(client_authn_method=CLIENT_AUTHN_METHOD) -info = { - "client_id": os.environ["OIDC_CLIENT_ID"], - "client_secret": os.environ["OIDC_CLIENT_SECRET"], - "redirect_uris": [f"{os.environ['OIDC_ROOT_URL']}/redirect_uri"], -} -client_reg = RegistrationResponse(**info) -client.store_registration_info(client_reg) + client.provider_config(os.environ["OIDC_PROVIDER"]) + + info = { + "client_id": os.environ["OIDC_CLIENT_ID"], + "client_secret": os.environ["OIDC_CLIENT_SECRET"], + } + client.store_registration_info(RegistrationResponse(**info)) + + client.redirect_uris = [f"{os.environ['OIDC_ROOT_URL']}/redirect_uri"] + + return client @app.route("/") def index(): + client = create_client() + session["state"] = rndstr() session["nonce"] = rndstr() @@ -47,7 +54,7 @@ def index(): "response_type": "code", "scope": os.environ["OIDC_SCOPES"].split(","), "nonce": session["nonce"], - "redirect_uri": client.registration_response["redirect_uris"][0], + "redirect_uri": client.redirect_uris[0], "state": session["state"], "claims": ClaimsRequest(id_token=Claims(acr=None, amr=None)), } @@ -59,6 +66,8 @@ def index(): @app.route("/redirect_uri") def oidc_callback(): + client = create_client() + response = request.query_string.decode("utf-8") aresp = client.parse_response( AuthorizationResponse, info=response, sformat="urlencoded" @@ -71,7 +80,6 @@ def oidc_callback(): error_response=aresp.to_dict(), ) - code = aresp["code"] logging.info("got auth code=%s", code) @@ -90,7 +98,20 @@ def oidc_callback(): logging.info("got userinfo=%s", userinfo) return jsonify( - access_token_response=access_token_response.to_dict(), userinfo=userinfo.to_dict() + access_token_response=access_token_response.to_dict(), + userinfo=userinfo.to_dict(), + ) + + +@app.errorhandler(InternalServerError) +def handle_server_exception(e): + exc = e.original_exception + import traceback + + return ( + f"""

Internal Server Error

+
{"".join(traceback.format_exception(exc))}
""", + 500, ) @@ -98,6 +119,6 @@ def oidc_callback(): def health(): return "OK" + if __name__ == "__main__": app.run(host="0.0.0.0") -