diff --git a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/etc/nevis/k8s-nevisauth-ac27dd7daad0ca2b7229bfaf.yaml b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/etc/nevis/k8s-nevisauth-ac27dd7daad0ca2b7229bfaf.yaml
index 38ac436..007acd6 100644
--- a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/etc/nevis/k8s-nevisauth-ac27dd7daad0ca2b7229bfaf.yaml
+++ b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/etc/nevis/k8s-nevisauth-ac27dd7daad0ca2b7229bfaf.yaml
@@ -46,7 +46,7 @@ spec:
podDisruptionBudget:
maxUnavailable: "50%"
git:
- tag: "r-28d025621af8913de776f24a3d4921835e1af78e"
+ tag: "r-52cf67aa5ec5c56333d2605f507c60bb29159968"
dir: "DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth"
credentials: "git-credentials"
keystores:
diff --git a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/EncodeAndDisplayToken.groovy b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/EncodeAndDisplayToken.groovy
new file mode 100644
index 0000000..2679729
--- /dev/null
+++ b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/EncodeAndDisplayToken.groovy
@@ -0,0 +1,19 @@
+import ch.nevis.esauth.auth.engine.AuthResponse
+import ch.nevis.esauth.util.httpclient.api.HttpClient
+
+if (outargs['out.JWTToken']) {
+ // we have a token
+ def header = "Bearer ${outargs['out.JWTToken']}"
+ response.setNote('agov.test.token', header)
+ notes.setProperty('agov.test.token', header)
+ response.removeOutArg('out.JWTToken')
+}
+
+// if (!response.getNote('agov.test.token')) {
+// response.setResult('newToken')
+// return
+//}
+
+
+// show the GUI
+response.setResult('display')
diff --git a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/esauth4.xml b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/esauth4.xml
index cc247ab..c5bdf4d 100644
--- a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/esauth4.xml
+++ b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/esauth4.xml
@@ -105,7 +105,7 @@
-
+
@@ -131,11 +131,14 @@
-
-
-
+
+
+
+
+
+
-
+
@@ -362,7 +365,7 @@
-
+
@@ -378,21 +381,222 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
@@ -598,12 +802,6 @@
-
-
-
-
-
-
@@ -1084,6 +1282,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1095,6 +1361,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/selectIdmProfile.groovy b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/selectIdmProfile.groovy
new file mode 100644
index 0000000..4951a61
--- /dev/null
+++ b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/selectIdmProfile.groovy
@@ -0,0 +1,74 @@
+import groovy.xml.XmlSlurper
+
+def idmSeverityRoleMap = [
+ "EnterpriseRoleAdmin": [11, "op-idmlogin.role.accs-mgmt-idm"],
+ "ClientRoot": [12, "op-idmlogin.role.support-priv"],
+ "AppAdmin": [20, "op-idmlogin.role.idmcfg-mgmt"],
+ "AppOwner": [5, "op-idmlogin.role.accs-mgmt-nonidm"],
+ "UserAndUnitAdmin": [7, "op-idmlogin.role.usr-unit-mgmt"],
+ "UserAdmin": [6, "op-idmlogin.role.usr-mgmt"],
+ "TemplateAdmin": [10, "op-idmlogin.role.support-basic"],
+ "Helpdesk": [1, "op-idmlogin.role.readonly-access" ]
+]
+
+try {
+ def dtoString = session['ch.adnovum.nevisidm.userDto']
+
+ def idmDto = new XmlSlurper().parseText(dtoString)
+ def idmPrfMap = idmDto.'**'.findAll
+ { prf -> prf.name() == 'profiles'
+ && prf.'**'.find
+ { role -> role.name() == 'roles'
+ && role.applicationName.text() == 'nevisIdm'
+ }
+ }.collectEntries { prf -> [ prf.extId.text(),
+ prf.'**'.findAll
+ { role -> role.name() == 'roles'
+ && role.applicationName.text() == 'nevisIdm'
+ }.collect{ rolePrioEntry -> idmSeverityRoleMap[rolePrioEntry.name.text()] ?: [1000, "DO-NOT-USE(${rolePrioEntry.name.text()})"]
+ }.sort { a, b -> a[0] <=> b[0] // sort by severity
+ }.last()[1] // take label of the ighest one
+ ] }
+
+ if ((inargs.getProperty('submit', '') == 'go') && idmPrfMap.containsKey(inargs.getProperty('profile_selection', 'missing'))) {
+
+ // user selected a profile which exists, we take it
+ def operationsProfileExtId = inargs.getProperty('profile_selection', 'missing')
+ LOG.info("User selected profile: ${operationsProfileExtId} '${idmPrfMap.get(operationsProfileExtId)}'")
+ response.setSessionAttribute('operationsProfileExtId', '' + operationsProfileExtId)
+ response.setResult('ok')
+ return
+
+ } else if (idmPrfMap.size() == 1) {
+
+ // we take the only profile, with an IDM role
+ def operationsProfileExtId = idmPrfMap.keySet().first()
+ LOG.info("taking the only profile with an idm role: ${operationsProfileExtId} '${idmPrfMap.get(operationsProfileExtId)}'")
+ response.setSessionAttribute('operationsProfileExtId', '' + operationsProfileExtId)
+ response.setResult('ok')
+ return
+
+ } else if (idmPrfMap.isEmpty()) {
+
+ // no profile with an IDM role, do nothing
+ response.setResult('ok')
+ return
+
+ } else {
+
+ // user should select a profile
+ response.setGuiName('op_idmlogin_select_profile')
+ idmPrfMap.each {
+ response.addRadioGuiField('profile_selection', it.value, it.key)
+ }
+ response.addButtonGuiField('submit', 'general.continue', 'go')
+
+ response.setStatus(ch.nevis.esauth.auth.engine.AuthResponse.AUTH_CONTINUE)
+ return
+ }
+} catch (Exception e) {
+ def errorMsg = "Failed to process profile selection: ${e.getMessage()}"
+ LOG.error(errorMsg, e)
+ response.setError(9901, errorMsg)
+ response.setResult('error')
+}
\ No newline at end of file
diff --git a/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/set_userextid_groovy_script_step.groovy b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/set_userextid_groovy_script_step.groovy
new file mode 100644
index 0000000..1fdd29c
--- /dev/null
+++ b/DEFAULT-ADN-AGOV-ADMIN-PROJECT/DEFAULT-ADN-AGOV-ADMIN-INV/auth/var/opt/nevisauth/default/conf/set_userextid_groovy_script_step.groovy
@@ -0,0 +1,59 @@
+try {
+ def s = request.getAuthSession(true)
+
+ LOG.debug("operationsExtId: ${notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserExtId']}")
+ LOG.debug("operationsUserProfileExtIdList: ${notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserProfileExtId']}")
+
+ // set operation's account extId and profile extid
+ if (notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserExtId'] == null || notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserProfileExtId'] == null) {
+ LOG.error("[OPACCESS] User ${notes['saml.assertion.subject']} tried to access without operations account or profile")
+ response.setResult('error');
+ return
+ }
+
+ response.setSessionAttribute('operationsExtId', notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserExtId'])
+
+ // extract additional attributes from assertion in session
+ if (notes['saml.attributes.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname']) {
+ response.setSessionAttribute('idp.firstName', notes['saml.attributes.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'])
+ }
+ if (notes['saml.attributes.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']) {
+ response.setSessionAttribute('idp.lastName', notes['saml.attributes.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'])
+ }
+ if (notes['saml.attributes.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']) {
+ response.setSessionAttribute('idp.email', notes['saml.attributes.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'])
+ }
+ if (notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/languageOfCorrespondance']) {
+ response.setSessionAttribute('idp.language', notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/languageOfCorrespondance'])
+ }
+
+ // we take the first one, if there is no profile in the operations unit
+ def unitAndProfileExtidPar = notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserProfileExtId']
+ .split(',').find{pairstr -> pairstr.split("\\\\")[1] == "130274ee-7e24-4050-9b94-d5717ef52ade" }
+ ?: notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserProfileExtId'].split(',')[0]
+
+ if (! unitAndProfileExtidPar.contains('130274ee-7e24-4050-9b94-d5717ef52ade') )
+ {
+ LOG.info("[OPACCESS] User ${notes['saml.assertion.subject']} with opaccount ${notes['saml.attributes.http://schemas.agov.ch/ws/2023/05/identity/claims/operationsUserExtId']} has no operations profile, we use the first one")
+ }
+ response.setSessionAttribute('operationsProfileExtId', unitAndProfileExtidPar.split("\\\\")[0])
+
+ // ad role based on agov aq level
+ def acrToRoleMap = [ 'urn:qa.agov.ch:names:tc:ac:classes:100':'AGOV-Loi.level100',
+ 'urn:qa.agov.ch:names:tc:ac:classes:200':'AGOV-Loi.level200',
+ 'urn:qa.agov.ch:names:tc:ac:classes:300':'AGOV-Loi.level300',
+ 'urn:qa.agov.ch:names:tc:ac:classes:400':'AGOV-Loi.level400',
+ 'urn:qa.agov.ch:names:tc:ac:classes:500':'AGOV-Loi.level500'
+ ]
+
+ if (acrToRoleMap[session['ch.nevis.auth.saml.assertion.authnContextClassRef']?='none']) {
+ response.addActualRole(acrToRoleMap[session['ch.nevis.auth.saml.assertion.authnContextClassRef']])
+ }
+
+
+ response.setResult('ok');
+
+} catch(Exception ex) {
+ LOG.warn("Exception in selectProfile groovy script: " + ex)
+ response.setResult('error');
+}