diff --git a/patterns/1d38203c48e017b5b3812385_resources/recovery_ongoing.groovy b/patterns/1d38203c48e017b5b3812385_resources/recovery_ongoing.groovy index 29bc8c5..5148074 100644 --- a/patterns/1d38203c48e017b5b3812385_resources/recovery_ongoing.groovy +++ b/patterns/1d38203c48e017b5b3812385_resources/recovery_ongoing.groovy @@ -1,4 +1,22 @@ +import ch.nevis.esauth.auth.engine.AuthResponse + if (inargs['recovery'] != null && inargs['recovery'] == 'recovery' ) { - response.setResult('ok') - return + // clean up SAML state, to make sure the redirect will really be processed + // IdentityProviderState sets session attributes as follows + // -session-participants. = + // State name contains the name of the pattern 'Recovery_redirectAgovMe' + def s = request.getAuthSession(true) + def sessionKeySet = new HashSet(session.keySet()) + sessionKeySet.each { key -> + if ( key ==~ /.*Recovery_redirectAgovMe-session-participants\.*/ ) { + LOG.info("Deleted session attribute '${key}'") + s.removeAttribute(key) + } + } + response.setResult('ok') + return } + +// if we reach this, display the GUI again +response.setStatus(AuthResponse.AUTH_CONTINUE) +return \ No newline at end of file diff --git a/patterns/1f0702aaabef60a615abf41f_resources/resources.zip b/patterns/1f0702aaabef60a615abf41f_resources/resources.zip index 42c7d8a..7580269 100644 Binary files a/patterns/1f0702aaabef60a615abf41f_resources/resources.zip and b/patterns/1f0702aaabef60a615abf41f_resources/resources.zip differ diff --git a/patterns/204c22beaccdfd22727af378_labels/labels.zip b/patterns/204c22beaccdfd22727af378_labels/labels.zip index 57cebaf..d897a5c 100644 Binary files a/patterns/204c22beaccdfd22727af378_labels/labels.zip and b/patterns/204c22beaccdfd22727af378_labels/labels.zip differ diff --git a/patterns/204c22beaccdfd22727af378_template/webdata.zip b/patterns/204c22beaccdfd22727af378_template/webdata.zip index 68828e0..23101bc 100644 Binary files a/patterns/204c22beaccdfd22727af378_template/webdata.zip and b/patterns/204c22beaccdfd22727af378_template/webdata.zip differ diff --git a/patterns/2cdd910036aa06b102863a4f_scriptFile/checkLoa.gy b/patterns/2cdd910036aa06b102863a4f_scriptFile/checkLoa.gy index d86fe01..5f56cba 100644 --- a/patterns/2cdd910036aa06b102863a4f_scriptFile/checkLoa.gy +++ b/patterns/2cdd910036aa06b102863a4f_scriptFile/checkLoa.gy @@ -185,42 +185,46 @@ try { } // no login for users with a recovery role - for (String role : getUserAGOVRecoveryRoles()) { - if (role == 'mustRecover') { - session.setAttribute('agov.recovery.authnContextClassRef', 'urn:qa.agov.ch:names:tc:ac:classes:mustRecover') - session.setAttribute('agov.recovery.authenticatedWith', session.getAttribute('authenticatedWith') ?: 'unknown' ) + def recoveryRoleList = getUserAGOVRecoveryRoles() + + if (recoveryRoleList.contains('mustRecover')) { + session.setAttribute('agov.recovery.authnContextClassRef', 'urn:qa.agov.ch:names:tc:ac:classes:mustRecover') + session.setAttribute('agov.recovery.authenticatedWith', session.getAttribute('authenticatedWith') ?: 'unknown' ) - def origIdVerification = getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString()) ?: 'None' + def origIdVerification = getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString()) ?: 'None' + def idVerification = getUserIdVerificationForRecovery() ?: origIdVerification + session.setAttribute('agov.recovery.currentIdVerification', '' + idVerification ) - def idVerification = getUserIdVerificationForRecovery() ?: origIdVerification - session.setAttribute('agov.recovery.currentIdVerification', '' + idVerification ) + // align currentAgovAq with the method selected for idVerification + def currentAgovAqForRecovery = getAqLevelBasedOnIdVerificationForRecovery(idVerification, highestRoleLevelNumber) + session.setAttribute('agov.recovery.currentAgovAq', '' + currentAgovAqForRecovery) - // align currentAgovAq with the method selected for idVerification - def currentAgovAqForRecovery = getAqLevelBasedOnIdVerificationForRecovery(idVerification, highestRoleLevelNumber) - session.setAttribute('agov.recovery.currentAgovAq', '' + currentAgovAqForRecovery) + def validFrom = getUserMustRecoverValidFrom() ?: '' + session.setAttribute('agov.recovery.currentAgovAqRoleValidFrom', '' + validFrom ) - def validFrom = getUserMustRecoverValidFrom() ?: '' - session.setAttribute('agov.recovery.currentAgovAqRoleValidFrom', '' + validFrom ) + LOG.debug("CheckLoa: mustRecover: origIdVerification=${origIdVerification}, idVerification=${idVerification}, currentAgovAqForRecovery=${currentAgovAqForRecovery}") - LOG.debug("CheckLoa: mustRecover: origIdVerification=${origIdVerification}, idVerification=${idVerification}, currentAgovAqForRecovery=${currentAgovAqForRecovery}") + response.setResult('exit.2') + return - response.setResult('exit.2') - return - - } else if (role == 'recovery') { + } else if (recoveryRoleList.contains('recovery')) { + if (recoveryRoleList.contains('recoveryCascade')) { + session.setAttribute('agov.recovery.authnContextClassRef', 'urn:qa.agov.ch:names:tc:ac:classes:recoveryCascade') + } else { session.setAttribute('agov.recovery.authnContextClassRef', 'urn:qa.agov.ch:names:tc:ac:classes:recovery') - session.setAttribute('agov.recovery.authenticatedWith', session.getAttribute('authenticatedWith') ?: 'unknown') - session.setAttribute('agov.recovery.currentAgovAq', session.getAttribute('contextClassRefToSet') ?: 'urn:qa.agov.ch:names:tc:ac:classes:100' ) - LOG.debug('CheckLoa: idVerification2= '+ getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString())) - def idVerification = getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString()) - session.setAttribute('agov.recovery.currentIdVerification', (idVerification.isEmpty() ? 'None' : idVerification.first())) - def validFrom = getUserAGOVLoiValidFrom('level'.concat(highestRoleLevelNumber.toString())) ?: '' - session.setAttribute('agov.recovery.currentAgovAqRoleValidFrom', validFrom) + } + session.setAttribute('agov.recovery.authenticatedWith', session.getAttribute('authenticatedWith') ?: 'unknown') + session.setAttribute('agov.recovery.currentAgovAq', session.getAttribute('contextClassRefToSet') ?: 'urn:qa.agov.ch:names:tc:ac:classes:100' ) + LOG.debug('CheckLoa: idVerification2= '+ getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString())) + def idVerification = getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString()) + session.setAttribute('agov.recovery.currentIdVerification', (idVerification.isEmpty() ? 'None' : idVerification.first())) + def validFrom = getUserAGOVLoiValidFrom('level'.concat(highestRoleLevelNumber.toString())) ?: '' + session.setAttribute('agov.recovery.currentAgovAqRoleValidFrom', validFrom) + + response.setResult('exit.2') + return + } - response.setResult('exit.2') - return - } - } if (highestRoleLevelNumber>=requestedRoleLevelNumber) { diff --git a/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip b/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip index 57cebaf..d897a5c 100644 Binary files a/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip and b/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip differ diff --git a/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip b/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip index 68828e0..23101bc 100644 Binary files a/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip and b/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip differ diff --git a/patterns/584964c837512845d7940809_authStatesFile/recovery-preprocessing.xml b/patterns/584964c837512845d7940809_authStatesFile/recovery-preprocessing.xml index 60aedba..c0a42d8 100644 --- a/patterns/584964c837512845d7940809_authStatesFile/recovery-preprocessing.xml +++ b/patterns/584964c837512845d7940809_authStatesFile/recovery-preprocessing.xml @@ -34,8 +34,8 @@ - - + + @@ -46,12 +46,10 @@ - - - + - + @@ -59,7 +57,7 @@ - + diff --git a/patterns/584964c837512845d7940809_resources/questionnaireLfProcessing.groovy b/patterns/584964c837512845d7940809_resources/questionnaireLfProcessing.groovy new file mode 100644 index 0000000..4a591a2 --- /dev/null +++ b/patterns/584964c837512845d7940809_resources/questionnaireLfProcessing.groovy @@ -0,0 +1,25 @@ +import ch.nevis.esauth.auth.engine.AuthResponse + +if (inargs['cancel'] && inargs['cancel'] == 'cancel') { + def s = request.getAuthSession(true) + s.removeAttribute('agov.recovery.moreThanOneLf') + + response.setResult('doCancel') + return +} + +if (inargs['continue'] && inargs['continue'] == 'yes') { + response.setSessionAttribute('agov.recovery.moreThanOneLf', 'yes') + response.setResult('loginFactorYes') + return +} + +if (inargs['continue'] && inargs['continue'] == 'no') { + response.setSessionAttribute('agov.recovery.moreThanOneLf', 'no') + response.setResult('loginFactorNo') + return +} + +// if we reach this, display the GUI again +response.setStatus(AuthResponse.AUTH_CONTINUE) +return \ No newline at end of file diff --git a/patterns/584964c837512845d7940809_resources/questionnaireReasonProcessing.groovy b/patterns/584964c837512845d7940809_resources/questionnaireReasonProcessing.groovy index e464736..0c0aba5 100644 --- a/patterns/584964c837512845d7940809_resources/questionnaireReasonProcessing.groovy +++ b/patterns/584964c837512845d7940809_resources/questionnaireReasonProcessing.groovy @@ -5,7 +5,11 @@ if (inargs['reason']) { } if (inargs['cancel'] && inargs['cancel'] == 'cancel') { - response.setResult('cancel') + def s = request.getAuthSession(true) + s.removeAttribute('agov.recovery.moreThanOneLf') + s.removeAttribute('agov.recovery.reason') + + response.setResult('doCancel') return } diff --git a/patterns/584964c837512845d7940809_resources/recovery-processing.groovy b/patterns/584964c837512845d7940809_resources/recovery-processing.groovy index 7db532f..b2cf851 100644 --- a/patterns/584964c837512845d7940809_resources/recovery-processing.groovy +++ b/patterns/584964c837512845d7940809_resources/recovery-processing.groovy @@ -164,6 +164,8 @@ if (session['ch.adnovum.nevisidm.userDto'] != null && notes['lasterror'] == null def hasRecoveryRole = userDto.'**'.find { node -> node.name() == 'roles' && node.applicationName.text() == 'AGOV-AccountStatus' && node.name.text() == 'recovery' } + def hasRecoveryCascadeRole = userDto.'**'.find { node -> node.name() == 'roles' && node.applicationName.text() == 'AGOV-AccountStatus' && node.name.text() == 'recoveryCascade' } + def hasNewLoginFactor = hasRecoveryRole && userHasNewLoginFactor() if (mustRecover) { @@ -176,6 +178,8 @@ if (session['ch.adnovum.nevisidm.userDto'] != null && notes['lasterror'] == null agovAqValidFrom = getUserMustRecoverValidFrom() maxLoi = getAqLevelBasedOnIdVerificationForRecovery(idVerification, maxLoi) + } else if (hasRecoveryCascadeRole && hasNewLoginFactor) { + response.setSessionAttribute('agov.recovery.authnContextClassRef', 'urn:qa.agov.ch:names:tc:ac:classes:recoveryCascade') } LOG.debug("Recovery: MaxLoi is '${maxLoi}'") diff --git a/patterns/6061abea33a234fad73897b7_authStatesFile/redirectToAgovMe.xml b/patterns/6061abea33a234fad73897b7_authStatesFile/redirectToAgovMe.xml index 063b491..d2e27b1 100644 --- a/patterns/6061abea33a234fad73897b7_authStatesFile/redirectToAgovMe.xml +++ b/patterns/6061abea33a234fad73897b7_authStatesFile/redirectToAgovMe.xml @@ -32,12 +32,12 @@ value="${sess:agov.recovery.currentAgovAqRoleValidFrom}"/> - + - + \ No newline at end of file diff --git a/patterns/Recovery_Auth_584964c837512845d7940809.yml b/patterns/Recovery_Auth_584964c837512845d7940809.yml index 322c2cb..db23858 100644 --- a/patterns/Recovery_Auth_584964c837512845d7940809.yml +++ b/patterns/Recovery_Auth_584964c837512845d7940809.yml @@ -3,6 +3,8 @@ pattern: id: "584964c837512845d7940809" className: "ch.nevis.admin.v4.plugin.nevisauth.patterns2.GenericAuthenticationStep" name: "Recovery_Auth" + notes: "TODO/haburger/2025-01-23: the transition exit.3 (alreadyInRecovery) is never\ + \ used. We should clean this up here" properties: authStatesFile: "res://584964c837512845d7940809#authStatesFile" parameters: "var://extid_user_verify-template-parameters"