# Sign in with the EU Digital Identity Wallet - Python (Flask + Authlib) # CodeB acts as the verifier: it asks the user's wallet for a presentation, # verifies it, and hands your app a signed OpenID Connect id_token. # # pip install flask authlib requests # SESSION_SECRET= CODEB_CLIENT_ID=... CODEB_CLIENT_SECRET=... python wallet-signin-python.py # # Register https:///callback as redirect URI for your client first. import os from flask import Flask, redirect, session, url_for from authlib.integrations.flask_client import OAuth ISSUER = os.environ.get("CODEB_ISSUER", "https://phone.aloaha.com") APP_BASE_URL = os.environ.get("APP_BASE_URL", "http://localhost:3000") WALLET_ACRS = ("urn:codeb:acr:eudi-wallet", "urn:codeb:acr:eudi-wallet-linked") app = Flask(__name__) app.secret_key = os.environ["SESSION_SECRET"] # long random value; signs the session cookie oauth = OAuth(app) oauth.register( "codeb", client_id=os.environ.get("CODEB_CLIENT_ID", ""), client_secret=os.environ.get("CODEB_CLIENT_SECRET", ""), server_metadata_url=ISSUER + "/.well-known/openid-configuration", client_kwargs={"scope": "openid profile email", "code_challenge_method": "S256"}, ) @app.route("/") def home(): u = session.get("user") if u: return "Signed in as %s (acr=%s)" % (u["sub"], u["acr"]) return 'Sign in with your EU Digital Identity Wallet' @app.route("/login") def login(): # acr_values sends the user straight to the wallet sign-in. return oauth.codeb.authorize_redirect(APP_BASE_URL + "/callback", acr_values=WALLET_ACRS[0]) @app.route("/callback") def callback(): # Checks state, nonce, signature, issuer, audience and expiry of the id_token. token = oauth.codeb.authorize_access_token() claims = token["userinfo"] # the validated id_token claims if claims.get("acr") not in WALLET_ACRS: return "This page needs a sign-in with the EU Digital Identity Wallet (acr=%s)." % claims.get("acr"), 403 session.clear() session["user"] = {"sub": claims["sub"], "acr": claims["acr"]} return redirect(url_for("home")) if __name__ == "__main__": app.run(port=int(os.environ.get("PORT", "3000")))