diff --git a/ci/python/flask-oidc-client/index.py b/ci/python/flask-oidc-client/index.py index 4a0317d..7a1b18b 100644 --- a/ci/python/flask-oidc-client/index.py +++ b/ci/python/flask-oidc-client/index.py @@ -1,3 +1,13 @@ +import argparse + +# Parser les arguments données sur la ligne de commande +parser = argparse.ArgumentParser() +parser.add_argument("--port") +parser.add_argument("--clientid") +parser.add_argument("--clientsecret") +parser.add_argument("--scopes") +args = parser.parse_args() + import urllib3 from flask import Flask, redirect, url_for, session, jsonify, request from authlib.integrations.flask_client import OAuth @@ -7,11 +17,11 @@ urllib3.disable_warnings() # Constantes à modifier si besoin -CLIENT_ID = "client-testcas" -CLIENT_SECRET = "secret-testcas" +CLIENT_ID = args.clientid +CLIENT_SECRET = args.clientsecret PROVIDER_METADATA_URL = "https://localhost:8443/cas/oidc/.well-known" -CLIENT_CALLBACK_URL = "http://localhost:8018/oidc/authorize" -SCOPES = "openid profile test" +CLIENT_CALLBACK_URL = "http://localhost:"+args.port+"/oidc/authorize" +SCOPES = args.scopes # Initialisation de l'app flask app = Flask(__name__) @@ -88,4 +98,4 @@ def logout(): # Démarrer l'application Flask if __name__ == '__main__': - app.run(host="0.0.0.0", port=8018) \ No newline at end of file + app.run(host="0.0.0.0", port=args.port) \ No newline at end of file diff --git a/ci/python/flask-oidc-client2/index.py b/ci/python/flask-oidc-client2/index.py deleted file mode 100644 index af17eb0..0000000 --- a/ci/python/flask-oidc-client2/index.py +++ /dev/null @@ -1,91 +0,0 @@ -import urllib3 -from flask import Flask, redirect, url_for, session, jsonify, request -from authlib.integrations.flask_client import OAuth -from authlib.oauth2.rfc6749.errors import OAuth2Error -from functools import wraps - -urllib3.disable_warnings() - -# Constantes à modifier si besoin -CLIENT_ID = "client2-testcas" -CLIENT_SECRET = "secret2-testcas" -PROVIDER_METADATA_URL = "https://localhost:8443/cas/oidc/.well-known" -CLIENT_CALLBACK_URL = "http://localhost:8020/oidc/authorize" -SCOPES = "openid" - -# Initialisation de l'app flask -app = Flask(__name__) -app.secret_key = "7f2d013e-1bfe-4a7a-9734-b40f57er5bbf" - -# Initialisation de l'OIDC avec Authlib -oauth = OAuth(app) - -# Configuration pour communiquer avec l'IDP OIDC -oauth.register( - name='oidc', - client_id=CLIENT_ID, - client_secret=CLIENT_SECRET, - server_metadata_url=PROVIDER_METADATA_URL, - client_kwargs={ - 'scope': SCOPES, - 'verify': False - } -) - -# Annotation à poser pour une route protégée par OIDC -def login_required(f): - @wraps(f) - def decorated_function(*args, **kwargs): - if "oidc" not in session: - return redirect(url_for('login')) - return f(*args, **kwargs) - return decorated_function - -# Affiche les informations de l'utilisateur -@app.route('/oidc/protected') -@login_required -def protected(): - return jsonify(session.get("oidc")) - -# Redirection vers le fournisseur OIDC avec la bonne URL de callback -@app.route('/oidc/login') -def login(): - return oauth.oidc.authorize_redirect(CLIENT_CALLBACK_URL) - -# Callback après authentification (GET) -# Callback après logout (POST) -@app.route('/oidc/authorize', methods=['GET', 'POST']) -def authorize(): - try: - # Récupérer AT, RT, ID Token et décoder l'ID Token dans le champ userinfo - token_response = oauth.oidc.authorize_access_token(**{'scope':SCOPES}) - # Stocker les tokens et infos utilisateur dans la session - session["oidc"] = token_response - return redirect(url_for("protected")) - except OAuth2Error as error: - return f"Erreur d'authentification : {error}" - -# Route pour récupérer les informations de l'utilisateur via l'endpoint UserInfo -@app.route('/oidc/userinfo') -@login_required -def userinfo(): - try: - # Récupérer l'access token stocké dans la session - token_response = session.get("oidc") - # Utiliser l'access token pour faire une requête au l'endpoint userinfo et la stocker en session - user_info = oauth.oidc.userinfo(token=token_response) - session["oidc"] = {**user_info, **session["oidc"].copy()} - return redirect(url_for("protected")) - except OAuth2Error as error: - return jsonify({"error": f"Erreur lors de la récupération des informations utilisateur : {error}"}), 400 - - -# Route de déconnexion -@app.route('/oidc/logout') -def logout(): - session.pop("oidc", None) - return redirect(url_for("protected")) - -# Démarrer l'application Flask -if __name__ == '__main__': - app.run(host="0.0.0.0", port=8020) \ No newline at end of file diff --git a/ci/python/flask-oidc-client3/index.py b/ci/python/flask-oidc-client3/index.py deleted file mode 100644 index 495ebaf..0000000 --- a/ci/python/flask-oidc-client3/index.py +++ /dev/null @@ -1,91 +0,0 @@ -import urllib3 -from flask import Flask, redirect, url_for, session, jsonify, request -from authlib.integrations.flask_client import OAuth -from authlib.oauth2.rfc6749.errors import OAuth2Error -from functools import wraps - -urllib3.disable_warnings() - -# Constantes à modifier si besoin -CLIENT_ID = "client3-testcas" -CLIENT_SECRET = "secret3-testcas" -PROVIDER_METADATA_URL = "https://localhost:8443/cas/oidc/.well-known" -CLIENT_CALLBACK_URL = "http://localhost:8021/oidc/authorize" -SCOPES = "openid" - -# Initialisation de l'app flask -app = Flask(__name__) -app.secret_key = "7f2d013e-1bfe-4a7a-9734-b40f57er78fa" - -# Initialisation de l'OIDC avec Authlib -oauth = OAuth(app) - -# Configuration pour communiquer avec l'IDP OIDC -oauth.register( - name='oidc', - client_id=CLIENT_ID, - client_secret=CLIENT_SECRET, - server_metadata_url=PROVIDER_METADATA_URL, - client_kwargs={ - 'scope': SCOPES, - 'verify': False - } -) - -# Annotation à poser pour une route protégée par OIDC -def login_required(f): - @wraps(f) - def decorated_function(*args, **kwargs): - if "oidc" not in session: - return redirect(url_for('login')) - return f(*args, **kwargs) - return decorated_function - -# Affiche les informations de l'utilisateur -@app.route('/oidc/protected') -@login_required -def protected(): - return jsonify(session.get("oidc")) - -# Redirection vers le fournisseur OIDC avec la bonne URL de callback -@app.route('/oidc/login') -def login(): - return oauth.oidc.authorize_redirect(CLIENT_CALLBACK_URL) - -# Callback après authentification (GET) -# Callback après logout (POST) -@app.route('/oidc/authorize', methods=['GET', 'POST']) -def authorize(): - try: - # Récupérer AT, RT, ID Token et décoder l'ID Token dans le champ userinfo - token_response = oauth.oidc.authorize_access_token(**{'scope':SCOPES}) - # Stocker les tokens et infos utilisateur dans la session - session["oidc"] = token_response - return redirect(url_for("protected")) - except OAuth2Error as error: - return f"Erreur d'authentification : {error}" - -# Route pour récupérer les informations de l'utilisateur via l'endpoint UserInfo -@app.route('/oidc/userinfo') -@login_required -def userinfo(): - try: - # Récupérer l'access token stocké dans la session - token_response = session.get("oidc") - # Utiliser l'access token pour faire une requête au l'endpoint userinfo et la stocker en session - user_info = oauth.oidc.userinfo(token=token_response) - session["oidc"] = {**user_info, **session["oidc"].copy()} - return redirect(url_for("protected")) - except OAuth2Error as error: - return jsonify({"error": f"Erreur lors de la récupération des informations utilisateur : {error}"}), 400 - - -# Route de déconnexion -@app.route('/oidc/logout') -def logout(): - session.pop("oidc", None) - return redirect(url_for("protected")) - -# Démarrer l'application Flask -if __name__ == '__main__': - app.run(host="0.0.0.0", port=8021) \ No newline at end of file diff --git a/puppeteer/scenarios/oidc_protocol.js b/puppeteer/scenarios/oidc_protocol.js index 9041be8..e96a8fc 100644 --- a/puppeteer/scenarios/oidc_protocol.js +++ b/puppeteer/scenarios/oidc_protocol.js @@ -35,12 +35,14 @@ const assert = require("assert"); //Verify that attributes were received assert(pageContent.includes("attributes")); - assert(pageContent.includes("isMemberOf")); - assert(pageContent.includes("\"cn\":\"TEST TEST\"")); - assert(pageContent.includes("\"nickname\":\"test1\"")); //Mapped attribute from ENTPersonLogin + assert(pageContent.includes("isMemberOf")); //Custom claim + assert(pageContent.includes("\"nickname\":\"test1\"")); //Mapped claim from ENTPersonLogin assert(pageContent.includes("\"uid\":[\"F1abc\"]")); - assert(pageContent.includes("\"mail\":[\"test.test@test.com\"]")); - + assert(pageContent.includes("\"family_name\":\"TEST\"")); //Mapped claim from cn + assert(pageContent.includes("\"given_name\":\"Test\"")); + assert(pageContent.includes("\"usual_name\":\"TEST\"")); //Mapped claim from cn + assert(!pageContent.includes("email")); //Not in scopes + process.exit(0) } catch (e) { diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 924f493..a14bb9d 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -115,9 +115,14 @@ cas.authn.saml-idp.core.entity-id: https://localhost:8443/cas/idp/metadata cas.authn.oidc.core.issuer: https://localhost:8443/cas/oidc cas.authn.oidc.jwks.file-system.jwks-file: /tmp/oidc/keystore.jwks cas.authn.oidc.core.claims-map.nickname: ENTPersonLogin -cas.authn.oidc.core.user-defined-scopes.test: uid,isMemberOf,cn,sn,givenName,displayName,mail +cas.authn.oidc.core.claims-map.given_name: givenName +cas.authn.oidc.core.claims-map.email: mail +cas.authn.oidc.core.claims-map.family_name: sn +cas.authn.oidc.core.claims-map.usual_name: sn +cas.authn.oidc.core.claims-map.name: displayName +cas.authn.oidc.core.user-defined-scopes.test: uid,isMemberOf,usual_name cas.authn.oidc.discovery.scopes: openid,profile,test -cas.authn.oidc.discovery.claims: sub,name,cn,nickname,family_name,uid,isMemberOf,sn,givenName,displayName,mail +cas.authn.oidc.discovery.claims: sub,name,nickname,usual_name,uid,isMemberOf,email,given_name,family_name cas.authn.oidc.id-token.include-id-token-claims: false # Attribute definition