Compare commits

..

No commits in common. "master" and "r-04ad6fd7455702c2a591f4a7b8d6c94222de911e" have entirely different histories.

11 changed files with 522 additions and 223 deletions

View File

@ -46,7 +46,7 @@ spec:
podDisruptionBudget: podDisruptionBudget:
maxUnavailable: "50%" maxUnavailable: "50%"
git: git:
tag: "r-d6878093aefa2bfb8cc241b61fff5fe94bc95282" tag: "r-9849dba282e5e9421988bf7092f242ff73d83ce5"
dir: "DEFAULT-ADN-AGOV-PROJECT/DEFAULT-ADN-AGOV-INV/auth-sts" dir: "DEFAULT-ADN-AGOV-PROJECT/DEFAULT-ADN-AGOV-INV/auth-sts"
credentials: "git-credentials" credentials: "git-credentials"
keystores: keystores:

View File

@ -20,8 +20,6 @@ Configuration:
level: "DEBUG" level: "DEBUG"
- name: "AgovCaptcha" - name: "AgovCaptcha"
level: "DEBUG" level: "DEBUG"
- name: "ArtifactResolutionService"
level: "DEBUG"
- name: "AuthEngine" - name: "AuthEngine"
level: "INFO" level: "INFO"
- name: "AuthPerf" - name: "AuthPerf"
@ -29,10 +27,8 @@ Configuration:
- name: "IdmAuth" - name: "IdmAuth"
level: "DEBUG" level: "DEBUG"
- name: "OpTrace" - name: "OpTrace"
level: "INFO"
- name: "Recovery"
level: "DEBUG" level: "DEBUG"
- name: "Saml" - name: "Recovery"
level: "DEBUG" level: "DEBUG"
- name: "Script" - name: "Script"
level: "DEBUG" level: "DEBUG"

View File

@ -46,7 +46,7 @@ spec:
podDisruptionBudget: podDisruptionBudget:
maxUnavailable: "50%" maxUnavailable: "50%"
git: git:
tag: "r-53c09bd6632aebeda2b892197a01a8f7f185561d" tag: "r-04ad6fd7455702c2a591f4a7b8d6c94222de911e"
dir: "DEFAULT-ADN-AGOV-PROJECT/DEFAULT-ADN-AGOV-INV/auth" dir: "DEFAULT-ADN-AGOV-PROJECT/DEFAULT-ADN-AGOV-INV/auth"
credentials: "git-credentials" credentials: "git-credentials"
database: database:

View File

@ -134,10 +134,14 @@
<!-- source: pattern://8dbec5bb024707d73fca93ef --> <!-- source: pattern://8dbec5bb024707d73fca93ef -->
<KeyObject name="https://trustbroker-idp.agov-w.azure.adnovum.net" certificate="/var/opt/keys/trust/idp-pem-atb/truststore.jks"/> <KeyObject name="https://trustbroker-idp.agov-w.azure.adnovum.net" certificate="/var/opt/keys/trust/idp-pem-atb/truststore.jks"/>
</KeyStore> </KeyStore>
<!-- source: pattern://b09a3092a59797b317c06ae4 --> <!-- source: pattern://122a5450f8611066c0a8e6bf -->
<KeyStore name="EncryptionKeys"> <KeyStore name="Store_IDP_AGOV_SEC">
<!-- source: pattern://b09a3092a59797b317c06ae4 --> <!-- source: pattern://122a5450f8611066c0a8e6bf -->
<KeyObject name="DefaultEncryptionKey" certificate="/var/opt/keys/trust/idp-pem-atb-enc/truststore.jks"/> <KeyObject name="Signer_IDP_AGOV_SEC" certificate="/var/opt/keys/own/idp-pem-signer/cert.pem" privateKey="/var/opt/keys/own/idp-pem-signer/keystore.jks" passPhrase="pipe:///var/opt/keys/own/idp-pem-signer/keypass"/>
<!-- source: pattern://122a5450f8611066c0a8e6bf -->
<KeyObject name="https://trustbroker.agov-d.azure.adnovum.net" certificate="/var/opt/keys/trust/idp-pem-atb/truststore.jks"/>
<!-- source: pattern://122a5450f8611066c0a8e6bf -->
<KeyObject name="Encrypt_https://trustbroker.agov-d.azure.adnovum.net" certificate="/var/opt/keys/trust/idp-pem-atb-enc/truststore.pem"/>
</KeyStore> </KeyStore>
<!-- source: pattern://cb8c63274fe346280de0ffd5 --> <!-- source: pattern://cb8c63274fe346280de0ffd5 -->
<KeyStore name="Auth_Realm_Mobile_FIDO_UAFKeyStore"> <KeyStore name="Auth_Realm_Mobile_FIDO_UAFKeyStore">
@ -164,10 +168,13 @@
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 --> <!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<Domain name="Auth_Realm_Main_IDP" default="false" inactiveInterval="1800" reauthInterval="0" resetAuthenticationCondition="#{ (inargs.containsKey('SAMLRequest') and session.containsKey('ch.nevis.auth.saml.request.id')) ? 'restart' : '' }"> <Domain name="Auth_Realm_Main_IDP" default="false" inactiveInterval="1800" reauthInterval="0" resetAuthenticationCondition="#{ (inargs.containsKey('SAMLRequest') and session.containsKey('ch.nevis.auth.saml.request.id')) ? 'restart' : '' }">
<Entry method="authenticate" state="Auth_Realm_Main_IDP_IDP_Status_Check"/> <Entry method="authenticate" state="Auth_Realm_Main_IDP_IDP_Status_Check"/>
<Entry method="authenticate" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SECSSO/.*$:true}"/>
<Entry method="authenticate" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SSO/.*$:true}"/> <Entry method="authenticate" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SSO/.*$:true}"/>
<Entry method="logout" state="Auth_Realm_Main_IDP_IDP_Status_Check"/> <Entry method="logout" state="Auth_Realm_Main_IDP_IDP_Status_Check"/>
<Entry method="logout" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SECSSO/.*$:true}"/>
<Entry method="logout" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SSO/.*$:true}"/> <Entry method="logout" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SSO/.*$:true}"/>
<Entry method="stepup" state="Auth_Realm_Main_IDP_Selector"/> <Entry method="stepup" state="Auth_Realm_Main_IDP_Selector"/>
<Entry method="stepup" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SECSSO/.*$:true}"/>
<Entry method="stepup" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SSO/.*$:true}"/> <Entry method="stepup" state="Auth_Realm_Main_IDP_IDP_Status_Check" selector="${request:currentResource:^http[s]?\u003A//[^/]+/SAML2/SSO/.*$:true}"/>
</Domain> </Domain>
<!-- source: pattern://cb8c63274fe346280de0ffd5 --> <!-- source: pattern://cb8c63274fe346280de0ffd5 -->
@ -431,8 +438,6 @@
<!-- source: pattern://73efd00d67082ff1eb927922 --> <!-- source: pattern://73efd00d67082ff1eb927922 -->
<ResultCond name="main" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP"/> <ResultCond name="main" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP"/>
<!-- source: pattern://73efd00d67082ff1eb927922 --> <!-- source: pattern://73efd00d67082ff1eb927922 -->
<ResultCond name="main_secure" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC"/>
<!-- source: pattern://73efd00d67082ff1eb927922 -->
<Response value="AUTH_CONTINUE"> <Response value="AUTH_CONTINUE">
<!-- source: pattern://73efd00d67082ff1eb927922 --> <!-- source: pattern://73efd00d67082ff1eb927922 -->
<Gui name="saml_dispatcher" label="title.saml.failed"> <Gui name="saml_dispatcher" label="title.saml.failed">
@ -860,10 +865,6 @@
<!-- source: pattern://92cb6d5256008a32f12ceb93 --> <!-- source: pattern://92cb6d5256008a32f12ceb93 -->
<property name="logoutTrigger" value="#{request['currentResource'].contains('logout') || inargs.containsKey('logout') || inargs.containsKey('SAMLLogout')}"/> <property name="logoutTrigger" value="#{request['currentResource'].contains('logout') || inargs.containsKey('logout') || inargs.containsKey('SAMLLogout')}"/>
<!-- source: pattern://92cb6d5256008a32f12ceb93 --> <!-- source: pattern://92cb6d5256008a32f12ceb93 -->
<property name="in.verify" value="Assertion, AuthnRequest, ArtifactResolve, ArtifactResponse"/>
<!-- source: pattern://92cb6d5256008a32f12ceb93 -->
<property name="in.prospectVerification" value="ArtifactResolve"/>
<!-- source: pattern://92cb6d5256008a32f12ceb93 -->
<property name="out.binding" value="http-post"/> <property name="out.binding" value="http-post"/>
<!-- source: pattern://92cb6d5256008a32f12ceb93 --> <!-- source: pattern://92cb6d5256008a32f12ceb93 -->
<property name="out.post.relayStateEncoding" value="HTML"/> <property name="out.post.relayStateEncoding" value="HTML"/>
@ -950,19 +951,6 @@
<!-- source: pattern://92cb6d5256008a32f12ceb93 --> <!-- source: pattern://92cb6d5256008a32f12ceb93 -->
<property name="out.attribute.http://schemas.agov.ch/ws/2025/07/identity/claims/op/conversationId" value="${inctx:connection.HttpHeader.traceparent:^([0-9a-f]+)-([0-9a-f]+)-([0-9a-f]+)-([0-9a-f]+)$:$2}"/> <property name="out.attribute.http://schemas.agov.ch/ws/2025/07/identity/claims/op/conversationId" value="${inctx:connection.HttpHeader.traceparent:^([0-9a-f]+)-([0-9a-f]+)-([0-9a-f]+)-([0-9a-f]+)$:$2}"/>
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="false" resumeState="false">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="default" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC_post"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="useArtifact" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC_artifact"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<Response value="AUTH_ERROR">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<Gui name="AuthErrorDialog"/>
</Response>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="condition:useArtifact" value="${sess:agov.idp.use.artifact:^true$}"/>
</AuthState>
<AuthState name="Auth_Realm_Main_IDP_ReturnTimeoutButKeepSession" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="false" resumeState="true"> <AuthState name="Auth_Realm_Main_IDP_ReturnTimeoutButKeepSession" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="false" resumeState="true">
<!-- source: pattern://826166d230a6a4849f2837ae --> <!-- source: pattern://826166d230a6a4849f2837ae -->
<Response value="AUTH_CONTINUE"> <Response value="AUTH_CONTINUE">
@ -1218,100 +1206,6 @@
<Arg name="ch.nevis.isiweb4.response.status" value="403"/> <Arg name="ch.nevis.isiweb4.response.status" value="403"/>
</Response> </Response>
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC_post" class="ch.nevis.esauth.auth.states.saml.IdentityProviderState" final="false" resumeState="true">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="IDP-initiated-ConcurrentLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Concurrent_Logout"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="IDP-initiated-SingleLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Prepare_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="LogoutCompleted" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Logout_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="LogoutFailed" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Logout_Fail"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="SP-initiated-ConcurrentLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Concurrent_Logout"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="SP-initiated-SingleLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Prepare_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="authenticate:IDP-initiated-SSO" next="Auth_Realm_Main_IDP_RequestedRoleLevel"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="authenticate:SP-initiated-SSO" next="Auth_Realm_Main_IDP_RequestedRoleLevel"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="invalidAssertionConsumerUrl" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="ok" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Prepare_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="stepup:IDP-initiated-SSO" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Selector"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="stepup:SP-initiated-SSO" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Selector"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<Response value="AUTH_ERROR">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<Gui name="saml_idp" label="title.saml.failed">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<GuiElem name="lasterror" type="error" label="error.saml.failed"/>
</Gui>
</Response>
<propertyRef name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.issuer" value="https://auth.agov-w.azure.adnovum.net/SAML2SEC/"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.binding" value="http-post"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.post.relayStateEncoding" value="HTML"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.encrypt" value="none"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.encrypt.keystoreref" value="EncryptionKeys"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.encrypt.keyobjectref" value="DefaultEncryptionKey"/>
</AuthState>
<AuthState name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC_artifact" class="ch.nevis.esauth.auth.states.saml.IdentityProviderState" final="false" resumeState="true">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="IDP-initiated-ConcurrentLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Concurrent_Logout"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="IDP-initiated-SingleLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Prepare_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="LogoutCompleted" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Logout_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="LogoutFailed" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Logout_Fail"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="SP-initiated-ConcurrentLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Concurrent_Logout"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="SP-initiated-SingleLogout" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Prepare_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="authenticate:IDP-initiated-SSO" next="Auth_Realm_Main_IDP_RequestedRoleLevel"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="authenticate:SP-initiated-SSO" next="Auth_Realm_Main_IDP_RequestedRoleLevel"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="invalidAssertionConsumerUrl" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP_SEC"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="ok" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Prepare_Done"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="stepup:IDP-initiated-SSO" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Selector"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<ResultCond name="stepup:SP-initiated-SSO" next="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Selector"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<Response value="AUTH_ERROR">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<Gui name="saml_idp" label="title.saml.failed">
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<GuiElem name="lasterror" type="error" label="error.saml.failed"/>
</Gui>
</Response>
<propertyRef name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_AGOV_IDP"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.issuer" value="https://auth.agov-w.azure.adnovum.net/SAML2SEC/"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.binding" value="http-artifact"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.post.relayStateEncoding" value="HTML"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.encrypt" value="none"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.encrypt.keystoreref" value="EncryptionKeys"/>
<!-- source: pattern://bb9e7806a04578e0ad468829 -->
<property name="out.encrypt.keyobjectref" value="DefaultEncryptionKey"/>
</AuthState>
<AuthState name="Auth_Realm_Main_IDP_Fido_Email_Verify" class="ch.nevis.idm.authstate.IdmUserVerifyState" final="false" resumeState="false"> <AuthState name="Auth_Realm_Main_IDP_Fido_Email_Verify" class="ch.nevis.idm.authstate.IdmUserVerifyState" final="false" resumeState="false">
<!-- source: pattern://7fb39bfd6c34685866a22180 --> <!-- source: pattern://7fb39bfd6c34685866a22180 -->
<ResultCond name="clientNotFound" next="Auth_Realm_Main_IDP_AuthnFailed_Client_NotFound"/> <ResultCond name="clientNotFound" next="Auth_Realm_Main_IDP_AuthnFailed_Client_NotFound"/>
@ -1516,7 +1410,7 @@
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Prepare_Done" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="false"> <AuthState name="Auth_Realm_Main_IDP_Prepare_Done" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="false">
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 --> <!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 -->
<ResultCond name="default" next="Auth_Realm_Main_IDP_Auth_Done"/> <ResultCond name="default" next="Auth_Realm_Main_IDP_IDP_AGOV_SEC_Authorization"/>
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 --> <!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 -->
<Response value="AUTH_DONE"> <Response value="AUTH_DONE">
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 --> <!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 -->
@ -1664,12 +1558,21 @@
<!-- source: pattern://306ce091fd87bad6174d9e8b --> <!-- source: pattern://306ce091fd87bad6174d9e8b -->
<property name="parameter.idm.httpclient.tls.trustStoreRef" value="EId_Compare_And_Update_IDM_Attributes"/> <property name="parameter.idm.httpclient.tls.trustStoreRef" value="EId_Compare_And_Update_IDM_Attributes"/>
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Auth_Done" class="ch.nevis.esauth.auth.states.standard.AuthDone" final="false"> <AuthState name="Auth_Realm_Main_IDP_IDP_AGOV_SEC_Authorization" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="false">
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 --> <ResultCond name="ok" next="Auth_Realm_Main_IDP_Auth_Done"/>
<Response value="AUTH_DONE"> <!-- source: pattern://76b897ee0646a882016810be -->
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 --> <ResultCond name="forbidden_0" next="Auth_Realm_Main_IDP_IDP_AGOV_SEC_Authorization"/>
<Gui name="ContinueResponse"/> <!-- source: pattern://76b897ee0646a882016810be -->
<ResultCond name="stepup" next="Auth_Realm_Main_IDP_Selector"/>
<!-- source: pattern://76b897ee0646a882016810be -->
<Response value="AUTH_ERROR">
<!-- source: pattern://76b897ee0646a882016810be -->
<Arg name="ch.nevis.isiweb4.response.status" value="403"/>
</Response> </Response>
<!-- source: pattern://76b897ee0646a882016810be -->
<property name="parameter.paths" value="^http[s]?\u003A//[^/]+/SAML2/SECSSO/.*$"/>
<!-- source: pattern://76b897ee0646a882016810be -->
<property name="script" value="file:///var/opt/nevisauth/default/conf/saml_idp_agov_sec_authorization.groovy"/>
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Auth_Done_GUI" class="ch.nevis.esauth.auth.states.standard.AuthDone" final="false" resumeState="true"> <AuthState name="Auth_Realm_Main_IDP_Auth_Realm_Main_IDP_Custom_Auth_Done_GUI" class="ch.nevis.esauth.auth.states.standard.AuthDone" final="false" resumeState="true">
<!-- source: pattern://cf0e8f8de1c8ac7345c5a6bb --> <!-- source: pattern://cf0e8f8de1c8ac7345c5a6bb -->
@ -1808,6 +1711,22 @@
<!-- source: pattern://306ce091fd87bad6174d9e8b --> <!-- source: pattern://306ce091fd87bad6174d9e8b -->
<property name="parameter.idm.httpclient.tls.trustStoreRef" value="EId_Compare_And_Update_IDM_Attributes"/> <property name="parameter.idm.httpclient.tls.trustStoreRef" value="EId_Compare_And_Update_IDM_Attributes"/>
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Auth_Done" class="ch.nevis.esauth.auth.states.standard.AuthDone" final="false">
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 -->
<Response value="AUTH_DONE">
<!-- source: pattern://6061abea33a234fad73897b7, pattern://359792ce61c28c723ab7d354, pattern://4fcfadb4a5c946ead7e6e995 -->
<Gui name="ContinueResponse"/>
</Response>
</AuthState>
<AuthState name="Auth_Realm_Main_IDP_Selector" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="false">
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<ResultCond name="nomatch" next="Auth_Realm_Main_IDP_Prepare_Done"/>
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<Response value="AUTH_ERROR">
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<Arg name="ch.nevis.isiweb4.response.status" value="403"/>
</Response>
</AuthState>
<AuthState name="Auth_Realm_Main_IDP_OnCancel_Dispatch" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="false"> <AuthState name="Auth_Realm_Main_IDP_OnCancel_Dispatch" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="false">
<!-- source: pattern://af4ec934e8efbef422f03926 --> <!-- source: pattern://af4ec934e8efbef422f03926 -->
<ResultCond name="AccessApp" next="Auth_Realm_Main_IDP_Mobile_NLess_Auth"/> <ResultCond name="AccessApp" next="Auth_Realm_Main_IDP_Mobile_NLess_Auth"/>
@ -2349,15 +2268,6 @@
<!-- source: pattern://9a8294b080ea769d22924af0 --> <!-- source: pattern://9a8294b080ea769d22924af0 -->
<property name="script" value="file:///var/opt/nevisauth/default/conf/checkInsufficientLoa.groovy"/> <property name="script" value="file:///var/opt/nevisauth/default/conf/checkInsufficientLoa.groovy"/>
</AuthState> </AuthState>
<AuthState name="Auth_Realm_Main_IDP_Selector" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="false">
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<ResultCond name="nomatch" next="Auth_Realm_Main_IDP_Prepare_Done"/>
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<Response value="AUTH_ERROR">
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<Arg name="ch.nevis.isiweb4.response.status" value="403"/>
</Response>
</AuthState>
<AuthState name="Auth_Realm_Mobile_FIDO_UAF_DirectFidoAuthRequired" class="ch.nevis.esauth.auth.states.directResponse.DirectResponseState" final="true" resumeState="false"> <AuthState name="Auth_Realm_Mobile_FIDO_UAF_DirectFidoAuthRequired" class="ch.nevis.esauth.auth.states.directResponse.DirectResponseState" final="true" resumeState="false">
<!-- source: pattern://cb8c63274fe346280de0ffd5 --> <!-- source: pattern://cb8c63274fe346280de0ffd5 -->
<Response value="AUTH_ERROR"> <Response value="AUTH_ERROR">
@ -3578,12 +3488,6 @@
<property name="out.keystoreref" value="Store_IDP_AGOV"/> <property name="out.keystoreref" value="Store_IDP_AGOV"/>
<!-- source: pattern://14efdcb489f3f295fcbdf811 --> <!-- source: pattern://14efdcb489f3f295fcbdf811 -->
<property name="out.keyobjectref" value="Signer_IDP_AGOV"/> <property name="out.keyobjectref" value="Signer_IDP_AGOV"/>
<!-- source: pattern://14efdcb489f3f295fcbdf811 -->
<property name="in.keystoreref" value="Store_IDP_AGOV"/>
<!-- source: pattern://14efdcb489f3f295fcbdf811 -->
<property name="in.verify" value="ArtifactResolve"/>
<!-- source: pattern://14efdcb489f3f295fcbdf811 -->
<property name="in.prospectVerification" value=""/>
</WebService> </WebService>
<!-- source: pattern://7022472ae407577ae604bbb8 --> <!-- source: pattern://7022472ae407577ae604bbb8 -->
<RESTService name="ManagementService" class="ch.nevis.esauth.rest.service.session.ManagementService"/> <RESTService name="ManagementService" class="ch.nevis.esauth.rest.service.session.ManagementService"/>

View File

@ -23,72 +23,54 @@ def redirect(String url) {
outargs.put('nevis.transfer.destination', url) outargs.put('nevis.transfer.destination', url)
} }
String getNormalisedSamlMessage(String parameter) { /**
if (parameter == null) { * Extracts the content of the Issuer element from a parsed SAML message.
* The Issuer is optional according to SAML specification but we need it for dispatching.
*
* @param xml - as parsed by Groovy XmlSlurper
* @return text content of Issuer element converted or null
*/
String getIssuer(GPathResult xml) {
return xml.depthFirst().find { GPathResult node -> {
node.name().endsWith(":Issuer") || node.name().equalsIgnoreCase("Issuer")
}
}?.text()
}
String getIssuer(String value) {
if (value == null) {
return return
} }
String text String text
byte[] decoded byte[] decoded
def parser = new XmlSlurper()
// if parameter is raw xml then continue otherwise try to parse the base64 encoding // if value is raw xml then continue otherwise try to parse the base64 encoding
if (parameter.startsWith("<")) { if (value.startsWith("<")) {
text = new String(parameter) text = new String(value)
} }
else { else {
decoded = parameter.decodeBase64() decoded = value.decodeBase64()
text = new String(decoded) text = new String(decoded)
LOG.info("received SAML request $value")
} }
return text
}
// after decoded, if redirect binding, we need to parse string to xml
String getNodeText(GPathResult xml, String nodeName) { if (text.startsWith("<")) {
return xml.depthFirst().find { GPathResult node -> { LOG.debug("assuming POST/SOAP binding")
node.name().endsWith(":${nodeName}") || node.name().equalsIgnoreCase(nodeName) // plain String (POST/SOAP parameter)
} def xml = parser.parseText(text)
}?.text()?.trim() return getIssuer(xml)
}
String getAttribute(GPathResult xml, String attributeName) {
return xml.depthFirst().find { GPathResult node -> {
node.attributes().containsKey(attributeName)
}
}?.attributes()?.get(attributeName)
}
String getNodeText(String parameter, String nodeName) {
String samlMessage = getNormalisedSamlMessage(parameter)
if (samlMessage == null) {
return
} }
def parser = new XmlSlurper() else {
def xml = parser.parseText(samlMessage) LOG.debug("assuming redirect binding")
return getNodeText(xml, nodeName) // should be deflate encoded (query parameter)
} def is = new InflaterInputStream(new ByteArrayInputStream(decoded), new Inflater(true))
def xml = parser.parse(is)
String getAttribute(String parameter, String attributeName) { return getIssuer(xml)
String samlMessage = getNormalisedSamlMessage(parameter)
if (samlMessage == null) {
return
} }
def parser = new XmlSlurper()
def xml = parser.parseText(samlMessage)
return getAttribute(xml, attributeName)
} }
String getIssuer(String value) { def dispatchIssuer(i2s, String issuer) {
return getNodeText(value, 'Issuer')
}
String getAttributeConsumingServiceIndex(String value) {
return getAttribute(value, 'AttributeConsumingServiceIndex')
}
String getProtocolBinding(String value) {
return getAttribute(value, 'ProtocolBinding')
}
def dispatchIssuer(i2s, String issuer, boolean secureMode) {
def result = i2s.get(issuer) def result = i2s.get(issuer)
if (result == null) { if (result == null) {
LOG.info("No SP found for issuer '$issuer'. Hint: check SAML SP Connector patterns.") LOG.info("No SP found for issuer '$issuer'. Hint: check SAML SP Connector patterns.")
@ -98,33 +80,22 @@ def dispatchIssuer(i2s, String issuer, boolean secureMode) {
if(parameters.get('epdMode') == 'artifact' && result == 'epd'){ if(parameters.get('epdMode') == 'artifact' && result == 'epd'){
LOG.debug("EPD: Artifact mode") LOG.debug("EPD: Artifact mode")
result = result + "_artifact" result = result + "_artifact"
} else if (result == 'main' && secureMode) { }else{
LOG.debug("AGOV: Secure mode requested") LOG.debug("EPD: POST mode")
result = result + "_secure" }
}
response.setResult(result) response.setResult(result)
session.put('saml.inbound.issuer', issuer) session.put("saml.inbound.issuer", issuer)
session.put('saml.idp.result', result) // remember decision for sub-sequent requests without a SAML message session.put('saml.idp.result', result) // remember decision for sub-sequent requests without a SAML message
} }
def dispatchIssuer(i2s, String issuer) {
dispatchIssuer(i2s, issuer, false)
}
def dispatchMessage(i2s, String message) { def dispatchMessage(i2s, String message) {
def issuer = getIssuer(message) def issuer = getIssuer(message)
def secureMode = (getAttributeConsumingServiceIndex(message) == '10101')
def useArtifact = ('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' == getProtocolBinding(message))
LOG.info("secureMode requested: ${secureMode}")
if (issuer == null) { if (issuer == null) {
LOG.info("No issuer found in incoming SAML message. Giving up.") LOG.info("No issuer found in incoming SAML message. Giving up.")
} }
session.put('saml.inbound.issuer', issuer) session.put("saml.inbound.issuer", issuer)
session.put('agov.idp.use.artifact', '' + useArtifact) dispatchIssuer(i2s, issuer)
dispatchIssuer(i2s, issuer, secureMode)
} }
if (parameters.get('logoutConfirmation') == 'true' && "stepup" == request.getMethod()) { if (parameters.get('logoutConfirmation') == 'true' && "stepup" == request.getMethod()) {

View File

@ -20,8 +20,6 @@ Configuration:
level: "DEBUG" level: "DEBUG"
- name: "AgovCaptcha" - name: "AgovCaptcha"
level: "DEBUG" level: "DEBUG"
- name: "ArtifactResolutionService"
level: "DEBUG"
- name: "AuthEngine" - name: "AuthEngine"
level: "INFO" level: "INFO"
- name: "AuthPerf" - name: "AuthPerf"
@ -29,10 +27,8 @@ Configuration:
- name: "IdmAuth" - name: "IdmAuth"
level: "DEBUG" level: "DEBUG"
- name: "OpTrace" - name: "OpTrace"
level: "INFO"
- name: "Recovery"
level: "DEBUG" level: "DEBUG"
- name: "Saml" - name: "Recovery"
level: "DEBUG" level: "DEBUG"
- name: "Script" - name: "Script"
level: "DEBUG" level: "DEBUG"

View File

@ -0,0 +1,179 @@
boolean isEnabled() {
def paths = parameters.get("paths")
if (paths && !paths.isEmpty()) {
for (path in paths.split(',')) {
String url = request.currentResource
if (url.matches(path)) {
return true
}
}
}
return false
}
boolean isLevel(String role) {
if (role != null && role.isNumber()) {
def number = Integer.parseInt(role)
if (number > 0 && number <= 9) {
return true
}
}
return false
}
int getCurrentLevel() {
int level = 1 // level 1 is reached by definition on successful authentication
// levels are stored as roles once the authentication is done
for (String role : response.getActualRoles()) {
if (isLevel(role)) {
Integer number = Integer.parseInt(role)
if (number > level) {
level = number
}
}
}
LOG.debug("current level: $level")
return level
}
Integer getRequestedLevel() {
// try to determine required level based on SAML request (SP-initiated)
def context = session['ch.nevis.auth.saml.request.authnContextClassRef']
if (context == null) {
// this is expected for non-Nevis SAML partners
LOG.debug("unable to determine required authentication level: no AuthnContext")
return null
}
String prefix = 'urn:nevis:level:'
Integer level = null
if (context.contains(prefix)) {
def start = context.indexOf(prefix) // the prefix can appear anywhere in the context but only once
def remainder = context.substring(start + prefix.length())
for (String candidate : remainder.split(',')) {
if (!candidate.isNumber()) {
continue // must be an actual role
}
def number = Integer.parseInt(candidate)
if (level == null || number < level) {
level = number
}
}
}
if (level == null) {
// an AuthnContext has been sent but it does not contain the required authentication level
LOG.debug("unable to determine required authentication level from request: $context")
}
else {
LOG.info("extracted required authentication level from request: $context -> $level")
}
return level
}
Integer getRequiredLevel(levels, String issuer) {
// try to determine required level based on request
def level = getRequestedLevel()
if (level != null) {
LOG.info("required authentication level from request: $level")
return level
}
// else determine required level based on configuration (IDP-initiated or no authnContextClassRef sent)
if (issuer != null && levels.containsKey(issuer)) {
level = levels[issuer]
LOG.debug("required authentication level for issuer $issuer defined as $level")
return level
}
// else return null
LOG.debug("required authentication level for issuer $issuer is not defined")
return null
}
void setAuthnContext() {
def parts = [] as Set
def authLevel = response.getAuthLevel()
if (authLevel != null) {
if (isLevel(authLevel)) {
parts.add("urn:nevis:level:$authLevel")
}
else { // might be legacy auth.weak / auth.strong
parts.add(authLevel)
}
}
for (String role : response.getActualRoles()) {
if (isLevel(role)) { // previous authLevels might have been added to the roles already
parts.add("urn:nevis:level:$role")
}
// levels can also be normal roles so we add them always
parts.add(role)
}
def value = parts.sort().join(",")
LOG.debug("calculated AuthnContextClassRef for SAML Response: $value")
session['saml.idp.response.authncontext'] = value
}
boolean stepupRequired(levels, String issuer) {
Integer requiredLevel = getRequiredLevel(levels, issuer)
if (requiredLevel == null) {
LOG.info("unable to determine required authentication level for request from issuer $issuer")
setAuthnContext()
return false
}
Integer currentLevel = getCurrentLevel()
if (currentLevel >= requiredLevel) {
LOG.info("required authentication level $requiredLevel has been reached (current level $currentLevel)")
setAuthnContext()
return false
}
LOG.info("required authentication level $requiredLevel has not been reached (current level $currentLevel) - session upgrade needed")
request.setRequiredRoles("$requiredLevel")
return true
}
boolean hasAnyRequiredRole(i2r, issuer) {
if (issuer != null && i2r.containsKey(issuer)) {
def roles = i2r[issuer]
for (role in response.getActualRoles()) {
if (roles.contains(role)) {
return true
}
}
}
}
if (!isEnabled()) {
LOG.info("skipping SAML authorization checks.")
response.setResult('ok') // skip execution
return
}
// issuer set by IdentityProviderState (SP-initiated)
def issuer = session['ch.nevis.auth.saml.request.issuer']
// issuer to minimum required authentication level
def i2l = [:]
if (stepupRequired(i2l, issuer)) {
LOG.info("authentication level stepup required.")
response.setResult("stepup")
return // we are done for now
}
// issuer to list of required roles
def i2r = [:]
// issuer to ResultCond name
def i2e = [:]
i2e.put('https://trustbroker.agov-d.azure.adnovum.net', 'forbidden_0')
if (!i2r.isEmpty() && !hasAnyRequiredRole(i2r, issuer)) {
LOG.info("required roles check failed.")
response.setResult(i2e[issuer])
return // we are done
}
response.setResult('ok')

View File

@ -0,0 +1,174 @@
import java.util.zip.Inflater
import java.util.zip.InflaterInputStream
import groovy.xml.XmlSlurper
import groovy.xml.slurpersupport.GPathResult
/**
* Gets the value of the Referer header.
* If the header is missing the fallback is returned.
*
* Do NOT remove this method.
* This method is used when SAML IDP / Dispatch Error Redirect is not set.
* A call to this method will be generated into this script (~line 157).
*
* @param fallback - value to return if the Referer header is missing
* @return value of header or fallback
*/
def getReferer(String fallback) {
return request.getHttpHeader('Referer') ?: fallback
}
def redirect(String url) {
outargs.put('nevis.transfer.type', 'redirect')
outargs.put('nevis.transfer.destination', url)
}
/**
* Extracts the content of the Issuer element from a parsed SAML message.
* The Issuer is optional according to SAML specification but we need it for dispatching.
*
* @param xml - as parsed by Groovy XmlSlurper
* @return text content of Issuer element converted or null
*/
static String getIssuer(GPathResult xml) {
return xml.depthFirst().find { GPathResult node -> {
node.name().endsWith(":Issuer") || node.name().equalsIgnoreCase("Issuer")
}
}?.text()
}
String getIssuer(String value) {
if (value == null) {
return
}
String text
byte[] decoded
def parser = new XmlSlurper()
// if value is raw xml then continue otherwise try to parse the base64 encoding
if (value.startsWith("<")) {
text = new String(value)
}
else {
decoded = value.decodeBase64()
text = new String(decoded)
LOG.info("received SAML request $value")
}
// after decoded, if redirect binding, we need to parse string to xml
if (text.startsWith("<")) {
LOG.debug("assuming POST/SOAP binding")
// plain String (POST/SOAP parameter)
def xml = parser.parseText(text)
return getIssuer(xml)
}
else {
LOG.debug("assuming redirect binding")
// should be deflate encoded (query parameter)
def is = new InflaterInputStream(new ByteArrayInputStream(decoded), new Inflater(true))
def xml = parser.parse(is)
return getIssuer(xml)
}
}
def dispatchIssuer(i2s, String issuer) {
def result = i2s.get(issuer)
if (result == null) {
throw new RuntimeException("No SP found for issuer '$issuer'. Hint: check SAML SP Connector patterns.")
}
response.setResult(result)
session.put("saml.inbound.issuer", issuer)
session.put('saml.idp.result', result) // remember decision for sub-sequent requests without a SAML message
}
def dispatchMessage(i2s, String message) {
def issuer = getIssuer(message)
if (issuer == null) {
throw new RuntimeException("No issuer found in incoming SAML message. Giving up.")
}
session.put("saml.inbound.issuer", issuer)
dispatchIssuer(i2s, issuer)
}
if (parameters.get('logoutConfirmation') == 'true' && "stepup" == request.getMethod()) {
String url = request.currentResource
def path = new URL(url).getPath()
if (path.endsWith("/logout")) {
// next AuthState will show a logout confirmation GUI
response.setResult('confirm')
return
}
}
// ensure session exists
if (request.getSession(false) == null) {
session = request.getSession(true).getData()
}
// issuer (any case) -> ResultCond name
def i2s = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)
i2s.put('https://trustbroker.agov-d.azure.adnovum.net', 'state0')
def spInitiatedAllowed = parameters.get('spInitiated') == 'true'
def idpInitiatedAllowed = parameters.get('idpInitiated') == 'true'
try {
if (spInitiatedAllowed && inargs.containsKey('SAMLRequest')) { // SP-initiated authentication
LOG.debug("found SAMLRequest parameter for SP-initiated authentication")
String message = inargs.get('SAMLRequest')
dispatchMessage(i2s, message)
return
}
if (inargs.containsKey('SAMLResponse')) { // response to IDP-initiated SAML Logout
LOG.debug("found SAMLResponse parameter")
String message = inargs.get('SAMLResponse')
dispatchMessage(i2s, message)
return
}
if (spInitiatedAllowed && inargs.containsKey('soapheader')) { // SP-initiated SOAP with soapheader
LOG.debug("found soapheader parameter for SP-initiated")
String message = inargs.get('soapheader')
dispatchMessage(i2s, message)
return
}
if (spInitiatedAllowed && inargs.containsKey('')) { // SP-initiated SOAP with empty
LOG.debug("found empty parameter for SP-initiated SOAP message")
String message = inargs.get('')
dispatchMessage(i2s, message)
return
}
String issuer = inargs['Issuer'] ?: inargs['issuer']
if (idpInitiatedAllowed && issuer != null) { // IDP-initiated authentication
LOG.debug("found Issuer parameter for IDP-initiated authentication")
dispatchIssuer(i2s, issuer)
return
}
// used as fallback in case of ?logout (we need an IdentityProviderState)
if (inargs.containsKey("logout") && session.containsKey('saml.idp.result')) {
def result = session.get('saml.idp.result')
LOG.debug("dispatching to last used ResultCond: $result")
response.setResult(result)
return
}
}
catch (RuntimeException e) {
LOG.error("Error while dispatching SAML message: ${e.message}")
}
def redirectEnabled = parameters.get('errorHandling') == 'redirect'
if (redirectEnabled) {
def location = getReferer('/')
LOG.info("Unable to dispatch request. Giving up and redirecting (back) to $location")
redirect(location)
}
else {
LOG.info("Unable to dispatch request. Giving up and showing error GUI.")
response.setResult('default')
}

View File

@ -0,0 +1,64 @@
def redirect(location) {
outargs.put('nevis.transfer.type', 'redirect')
outargs.put('nevis.transfer.destination', location)
}
def getReturnURL() {
if (inargs.containsKey('return')) {
return inargs.get('return')
}
// determine returnURL based on Referer header (if present and not pointing to this page)
def referer = request.getHttpHeader('Referer')
if (referer == null) {
LOG.debug('no Referer header found')
return null
}
// strip query String for comparison
String previous = referer.contains('?') ? referer.substring(0, referer.indexOf("?")) : referer
def current = request.getCurrentResource()
if (current.startsWith(previous)) {
LOG.debug("Referer header $referer cannot be used as return URL - cyclic redirect")
return null
}
return referer
}
if (inargs.containsKey('logout-confirm')) {
def current = request.getCurrentResource()
// user has confirmed logout -> replace /logout with /?logout
String location
if (current.contains('?')) {
location = current.replace("/logout?", "/?logout&")
}
else {
location = current.replace("/logout", "/?logout")
}
redirect(location)
return
}
if (inargs.containsKey('logout-abort')) {
// user has aborted logout -> redirect to stored return URL
def location = session.get('logout-abort-url')
redirect(location)
return
}
// user has not clicked any button -> render GUI
response.setGuiName('saml_logout_confirm')
response.setGuiLabel('title.logout.confirmation')
// not setting a target as the API has been removed
response.addInfoGuiField('info', 'info.logout.confirmation', null)
response.addButtonGuiField('logout-confirm', 'continue.button.label', 'true')
def returnURL = getReturnURL()
if (returnURL != null) {
// store return URL in session
session.put('logout-abort-url', returnURL)
}
if (session.containsKey('logout-abort-url')) {
// add cancel button to go back
response.addButtonGuiField('logout-abort', 'cancel.button.label', 'true')
}

View File

@ -47,7 +47,7 @@ spec:
podDisruptionBudget: podDisruptionBudget:
maxUnavailable: "50%" maxUnavailable: "50%"
git: git:
tag: "r-0574c5a2098562d6585435194234bdb2b0cf0858" tag: "r-04ad6fd7455702c2a591f4a7b8d6c94222de911e"
dir: "DEFAULT-ADN-AGOV-PROJECT/DEFAULT-ADN-AGOV-INV/proxy-idp" dir: "DEFAULT-ADN-AGOV-PROJECT/DEFAULT-ADN-AGOV-INV/proxy-idp"
credentials: "git-credentials" credentials: "git-credentials"
database: database:

View File

@ -1112,6 +1112,11 @@
<url-pattern>/pwreset/*</url-pattern> <url-pattern>/pwreset/*</url-pattern>
</filter-mapping> </filter-mapping>
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 --> <!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<filter-mapping>
<filter-name>SessionHandler_Auth_Realm_Main_IDP</filter-name>
<url-pattern>/SAML2/SECSSO/*</url-pattern>
</filter-mapping>
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<filter-mapping> <filter-mapping>
<filter-name>SessionHandler_Auth_Realm_Main_IDP</filter-name> <filter-name>SessionHandler_Auth_Realm_Main_IDP</filter-name>
<url-pattern>/SAML2/SSO/*</url-pattern> <url-pattern>/SAML2/SSO/*</url-pattern>
@ -1203,6 +1208,11 @@
<url-pattern>/pwreset/*</url-pattern> <url-pattern>/pwreset/*</url-pattern>
</filter-mapping> </filter-mapping>
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 --> <!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<filter-mapping>
<filter-name>AuthenticationService_Auth_Realm_Main_IDP</filter-name>
<url-pattern>/SAML2/SECSSO/*</url-pattern>
</filter-mapping>
<!-- source: pattern://4fcfadb4a5c946ead7e6e995 -->
<filter-mapping> <filter-mapping>
<filter-name>AuthenticationService_Auth_Realm_Main_IDP</filter-name> <filter-name>AuthenticationService_Auth_Realm_Main_IDP</filter-name>
<url-pattern>/SAML2/SSO/*</url-pattern> <url-pattern>/SAML2/SSO/*</url-pattern>
@ -1635,10 +1645,10 @@
<param-value>true</param-value> <param-value>true</param-value>
</init-param> </init-param>
</servlet> </servlet>
<!-- source: pattern://e0fda9336be9c69dafc9b69e, pattern://a6f6dc6affdc7c692ff857b9, pattern://decb9b3f88d430fb5c95f466 --> <!-- source: pattern://e0fda9336be9c69dafc9b69e, pattern://76b897ee0646a882016810be, pattern://a6f6dc6affdc7c692ff857b9, pattern://decb9b3f88d430fb5c95f466 -->
<servlet> <servlet>
<servlet-name>Hosting_Default</servlet-name> <servlet-name>Hosting_Default</servlet-name>
<!-- source: pattern://e0fda9336be9c69dafc9b69e, pattern://a6f6dc6affdc7c692ff857b9, pattern://decb9b3f88d430fb5c95f466 --> <!-- source: pattern://e0fda9336be9c69dafc9b69e, pattern://76b897ee0646a882016810be, pattern://a6f6dc6affdc7c692ff857b9, pattern://decb9b3f88d430fb5c95f466 -->
<servlet-class>ch::nevis::isiweb4::servlet::defaults::DefaultServlet</servlet-class> <servlet-class>ch::nevis::isiweb4::servlet::defaults::DefaultServlet</servlet-class>
</servlet> </servlet>
<!-- source: pattern://097929211988398a87bcbb0c --> <!-- source: pattern://097929211988398a87bcbb0c -->
@ -1754,6 +1764,11 @@
<servlet-name>Hosting_Default</servlet-name> <servlet-name>Hosting_Default</servlet-name>
<url-pattern>/AUTH/RECOVERY/*</url-pattern> <url-pattern>/AUTH/RECOVERY/*</url-pattern>
</servlet-mapping> </servlet-mapping>
<!-- source: pattern://76b897ee0646a882016810be -->
<servlet-mapping>
<servlet-name>Hosting_Default</servlet-name>
<url-pattern>/SAML2/SECSSO/*</url-pattern>
</servlet-mapping>
<!-- source: pattern://a6f6dc6affdc7c692ff857b9 --> <!-- source: pattern://a6f6dc6affdc7c692ff857b9 -->
<servlet-mapping> <servlet-mapping>
<servlet-name>Hosting_Default</servlet-name> <servlet-name>Hosting_Default</servlet-name>