diff --git a/ci/python/flask-saml-client/index.py b/ci/python/flask-saml-client/index.py index 421cf26..ad04987 100644 --- a/ci/python/flask-saml-client/index.py +++ b/ci/python/flask-saml-client/index.py @@ -160,4 +160,4 @@ def metadata(): if __name__ == "__main__": - app.run(host="0.0.0.0", port=8011, debug=True) + app.run(host="0.0.0.0", port=8011) diff --git a/ci/python/service_test10.py b/ci/python/service_test10.py index 1785b0c..1a7898a 100644 --- a/ci/python/service_test10.py +++ b/ci/python/service_test10.py @@ -1,7 +1,7 @@ """ Serveur python simulant un service web. Il n'est pas là pour faire les requêtes (ce sont les scripts de test qui les font) mais pour pour faire valider des ST. -Utilisé comme service vers lequel on va être redirigé pour le test du multidomaine. +Utilisé comme service vers lequel on va être redirigé pour le test attribute release externalid. """ import urllib3 diff --git a/ci/python/service_test16.py b/ci/python/service_test16.py index 05eb76c..7980bd7 100644 --- a/ci/python/service_test16.py +++ b/ci/python/service_test16.py @@ -1,7 +1,7 @@ """ Serveur python simulant un service web. Il n'est pas là pour faire les requêtes (ce sont les scripts de test qui les font) mais pour pour faire valider des ST. -Utilisé comme service vers lequel on va être redirigé pour le test du multidomaine. +Utilisé comme service vers lequel on va être redirigé pour le test de la redirection portail token. """ import urllib3 diff --git a/puppeteer/run.sh b/puppeteer/run.sh index 1c6c01d..80b0954 100755 --- a/puppeteer/run.sh +++ b/puppeteer/run.sh @@ -64,6 +64,7 @@ echo -n "Node version: " && node --version # Installation des dépendances python cd "${ROOT_DIRECTORY}" pip install -r ci/python/flask-saml-client/requirements.txt +pip install -r ci/python/flask-oidc-client/requirements.txt # Démarrage des dockers redis et ldap cd "${ROOT_DIRECTORY}/ci/ldap" @@ -87,6 +88,12 @@ python3 externalid_api.py & pid_python_externalid_api=$! cd "flask-saml-client" python3 index.py & +pid_python_saml_client=$! +cd "../flask-oidc-client" +python3 index.py & +pid_python_oidc_client=$! +rm -r /tmp/oidc +mkdir /tmp/oidc cd "${ROOT_DIRECTORY}" # Lancement du serveur CAS grâce au war qu'on a construit plus haut @@ -154,7 +161,8 @@ kill -9 "$pid_python_service_test10" kill -9 "$pid_python_service_test16" kill -9 "$pid_python_structs_info_api" kill -9 "$pid_python_externalid_api" -ps -aux | grep "python3 index.py" | head -n 2 | awk '{print $2}' | xargs kill -9 +kill -9 "$pid_python_saml_client" +kill -9 "$pid_python_oidc_client" cd "${ROOT_DIRECTORY}/ci/ldap" ./stop-ldap.sh cd "${ROOT_DIRECTORY}/ci/redis" diff --git a/puppeteer/scenarios/oidc_protocol.js b/puppeteer/scenarios/oidc_protocol.js new file mode 100644 index 0000000..9041be8 --- /dev/null +++ b/puppeteer/scenarios/oidc_protocol.js @@ -0,0 +1,52 @@ +const cas = require("../cas.js"); +const puppeteer = require('puppeteer'); +const assert = require("assert"); + +(async () => { + const browser = await puppeteer.launch(cas.browserOptions()); + + try { + const page = await browser.newPage(); + const client = await page.createCDPSession(); + + // Login to cas + await page.goto("http://localhost:8018/oidc/protected"); + await cas.typeCredentialsAndEnter(page, "test1", "test"); + await page.waitForNavigation(); + + // Assert that TGC exists + await cas.verifyTGC(client) + + // waitForNetworkIdle is necessary in that case to obtain pageContent, or we get an error "Execution context was destroyed" + await page.waitForNetworkIdle(); + var pageContent = await page.content(); + + // Assert we have recevied tokens from the CAS + assert(pageContent.includes("access_token")); + assert(pageContent.includes("id_token")); + assert(pageContent.includes("refresh_token")); + assert(pageContent.includes("\"aud\":\"client-testcas\"")); + assert(pageContent.includes("\"iss\":\"https://localhost:8443/cas/oidc\"")); + assert(pageContent.includes("\"sub\":\"F1abc\"")); + + // Call userinfo OIDC endpoint to retrieve user attributes + await page.goto("http://localhost:8018/oidc/userinfo"); + pageContent = await page.content(); + + //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("\"uid\":[\"F1abc\"]")); + assert(pageContent.includes("\"mail\":[\"test.test@test.com\"]")); + + process.exit(0) + + } catch (e) { + cas.loge(e); + process.exit(1) + } finally { + await browser.close(); + } +})(); diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 4bf6cc7..873b16e 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -39,13 +39,13 @@ cas.interrupt.cookie.crypto.enabled: true cas.interrupt.cookie.crypto.encryption.key: Zw6N5Bs0vOQKxON6rb52hr5X6h9zi-BJeOs7oS1nQSk cas.interrupt.cookie.crypto.signing.key: Yf1GaNfRqKzezShY3Jr0SfP_UVxaIkegsLd9eOPBrFDzNaoJRurs-8d37dN_nEqqjrFsoEtNy_32RC74vRo0IA # OAuth -cas.authn.oauth.crypto.encryption.key: UfXfteRBAROe_VlXtsnBw5kIwrqAZc7SfPtnTW7llN0 +cas.authn.oauth.crypto.encryption.key: -a3HCYBRYDCcnskNvLMiw_cUgd28PZllv8oRlRWUD8zyVCjMaVn2LKbrEXzxz3tGcxLDB99bJr9cyA9OieKBig cas.authn.oauth.crypto.signing.key: XJeUdyaPKz4GHNWmjlFeKlEkGlVPqFTJbOmX8ezbao9lpucrtk5IA9GX3yC6ibVe7Wa-ze4RNhD62Z2v3N8wyA -cas.authn.oauth.access-token.crypto.encryption.key: mFcyXaH00ZIIXW0dI4Djat0NH7Cdvu-2UiinjiO5SFE +cas.authn.oauth.access-token.crypto.encryption.key: Jv1r8eGlQ5imRzk6g2lY5e7gFo-HISohmb7iYivfOPxauWjojsHomW58_7ChyitAe3Jdio64UneRx7FGW4z2dg cas.authn.oauth.access-token.crypto.signing.key: RfjL0ADLFzj4u5jhj6ysNk4G2P2-FIiPm04TYiENbktq-RO9zwQwsQzLg2496UlQiLNnpu1NJq7dcvsv5xDYjw -cas.authn.oauth.session-replication.cookie.crypto.encryption.key: hzB0RZ1NISOI0OFswtzUvaksvGobVHPeMllt4src0Po +cas.authn.oauth.session-replication.cookie.crypto.encryption.key: FuUHa2yjd9FdfTeQsNZuN3gGG2liISzASC5GjhuCkkKSP5L8p0m1MsGjs_ITQAC4n6cMMseSIqmm0twr-wFl4A cas.authn.oauth.session-replication.cookie.crypto.signing.key: q1U_Kp0qgl6uMKdVE_k4jvvE-zb3IxdtP5eIxLWbjOy74vYkfYSXspbLXR327F4D7qtuXI4DIVnvU5vEe8sH2Q -cas.authn.pac4j.core.session-replication.cookie.crypto.encryption.key: Fam8ftR1s0HgGzEyJv1r7CS48a5vER8fKPsCIB7Mv7g +cas.authn.pac4j.core.session-replication.cookie.crypto.encryption.key: s_3Q9UuJRjieQE5zWMYz91ZhSyigVoJ4CPBymGg-KF7iWCzVfXxcANhSUKD24sWWiJq1Q3g7utTQkK93e61Rxg cas.authn.pac4j.core.session-replication.cookie.crypto.signing.key: H9q5Z1Wog_iEzUbF021Z4d1ASDvUPHKeHekUUj4lX_Y5N57WLIyb1KxIUgtfQ6nXLoNRpejk84PDTyQO4fwXOA # Service ticket registry @@ -84,6 +84,15 @@ cas.interrupt.core.trigger-mode: AFTER_SSO # SAML cas.authn.saml-idp.core.entity-id: https://localhost:8443/cas/idp/metadata +# OIDC +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.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.id-token.include-id-token-claims: false + # Custom Properties # Interrupt