257 lines
12 KiB
Plaintext
257 lines
12 KiB
Plaintext
import org.codehaus.groovy.runtime.StackTraceUtils
|
|
import groovy.xml.XmlSlurper
|
|
|
|
def getUserAGOVLoiRoles() {
|
|
// set attibutes from DTO: -> AGOVaq
|
|
def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
return list.'**'.findAll { node -> node.name() == 'roles' && node.applicationName.text() == 'AGOV-Loi' }.collect({ node -> node.name.text() })
|
|
}
|
|
|
|
def getUserAGOVRecoveryRoles() {
|
|
// set attibutes from DTO: -> AGOV
|
|
def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
return list.'**'.findAll { node -> node.name() == 'roles' && node.applicationName.text() == 'AGOV-AccountStatus' }.collect({ node -> node.name.text() })
|
|
}
|
|
|
|
def getUserAGOVLoiIdVerification() {
|
|
// set attibutes from DTO: -> idVerification
|
|
def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
return list.'**'.findAll {node -> node.name() == 'properties' && node.name.text() == 'idVerification' && node.scopeName.text().contains('AGOV-Loi,')}.collect({ node -> node.value.text()})
|
|
}
|
|
|
|
def getUserAGOVLoiIdVerification(level) {
|
|
// set attibutes from DTO: -> idVerification
|
|
def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
return list.'**'.findAll {node -> node.name() == 'properties' && node.name.text() == 'idVerification' && node.scopeName.text() == 'AGOV-Loi,level' + level}.collect({ node -> node.value.text()})
|
|
}
|
|
|
|
def getUserAGOVLoiValidFrom(level) {
|
|
// set attibutes from DTO: -> validFrom
|
|
def payload = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
return payload.'**'.find {node -> node.name() == 'authorizations' && node.role.name.text() == level}?.validFrom?.text()
|
|
}
|
|
|
|
def getUserAGOVLoiValidTo(level) {
|
|
// set attibutes from DTO: -> validTo
|
|
def payload = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
return payload.'**'.find {node -> node.name() == 'authorizations' && node.role.name.text() == level}?.validTo?.text()
|
|
}
|
|
|
|
def getUserIdVerificationForRecovery() {
|
|
// application is AGOV-AccountStatus
|
|
def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
def result = list.'**'.find {node -> node.name() == 'properties' && node.name.text() == 'idVerification' && node.scopeName.text() == 'AGOV-AccountStatus,mustRecover'}?.value?.text()
|
|
|
|
if (!result) {
|
|
// fallback if not explicitly set
|
|
def currentLoaRole = getUserAGOVLoiRoles()?.sort()?.last() ?: 'level100'
|
|
def chDomicile = list.country.text() == 'ch'
|
|
def lastIdVerification = list.'**'.find {node -> node.name() == 'properties' && node.name.text() == 'idVerification' && node.scopeName.text() == 'AGOV-Loi,' + currentLoaRole}?.value?.text()
|
|
switch (currentLoaRole) {
|
|
case 'level100':
|
|
result = chDomicile ? 'SimpleLetter' : 'Video'
|
|
break
|
|
case 'level200':
|
|
result = chDomicile ? 'Bmid' : 'Video'
|
|
break
|
|
case 'level300':
|
|
case 'level400':
|
|
result = chDomicile ? lastIdVerification : 'Video'
|
|
break
|
|
default:
|
|
LOG.warn("unexpected loa on account: ${currentLoaRole}")
|
|
// safest default, should work in any case
|
|
result = 'Video'
|
|
}
|
|
LOG.warn("Recovery method not set, choosing ${result} (based on currentLoad: ${currentLoaRole}, CH-domicile: ${chDomicile}, last verification method: ${lastIdVerification})")
|
|
}
|
|
return result
|
|
}
|
|
|
|
def getAqLevelBasedOnIdVerificationForRecovery(idVerification, highestRoleLevelNumber) {
|
|
def result = 'urn:qa.agov.ch:names:tc:ac:classes:'
|
|
|
|
switch (idVerification) {
|
|
case 'None':
|
|
result = result.concat('100')
|
|
break
|
|
case 'SimpleLetter':
|
|
result = result.concat('200')
|
|
break
|
|
case 'Video':
|
|
case 'VideoSelfPaid':
|
|
case 'Bmid':
|
|
case 'BmidSelfPaid':
|
|
case 'Counter':
|
|
result = result.concat((highestRoleLevelNumber == 400) ? '400' : '300')
|
|
break
|
|
default:
|
|
LOG.warn("unexpected idVerification for recovery on account: ${idVerification}")
|
|
// safest default, should work in any case
|
|
result = result.concat('' + highestRoleLevelNumber)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
def getUserMustRecoverValidFrom() {
|
|
// set attibutes from DTO: -> validFrom
|
|
def payload = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
|
|
def authzNode = payload.'**'.find {node -> node.name() == 'authorizations' && node.role.name.text() == 'mustRecover'}
|
|
return (authzNode) ? ((authzNode.validFrom && !authzNode.validFrom.text().isEmpty()) ? authzNode.validFrom?.text() : authzNode.ctlCreDat?.text()) : ''
|
|
}
|
|
|
|
// Accounting
|
|
def requester = session['ch.nevis.auth.saml.request.scoping.requesterId'] ?: 'unknown'
|
|
def requestId = session['ch.nevis.auth.saml.request.id'] ?: 'unknown'
|
|
def requestedAq = session['agov.requestedRoleLevel'] ?: 'unknown'
|
|
def user = session['ch.adnovum.nevisidm.user.extId'] ?: 'unknown'
|
|
def credentialType = session['authenticatedWith'] ?: 'unknown'
|
|
def sourceIp = request.getLoginContext()['connection.HttpHeader.X-Real-IP'] ?: 'unknown'
|
|
def userAgent = request.getLoginContext()['connection.HttpHeader.user-agent'] ?: request.getLoginContext()['connection.HttpHeader.User-Agent'] ?: 'unknown'
|
|
|
|
try {
|
|
// beef
|
|
def session = request.getAuthSession(true)
|
|
def highestRoleLevelNumber = 0
|
|
def requestedRoleLevelNumber = session.get('agov.requestedRoleLevel').toInteger()
|
|
def adressVerificationList = getUserAGOVLoiIdVerification('200')
|
|
def adressVerification = 'None'
|
|
if (adressVerificationList && !adressVerificationList.isEmpty()) {
|
|
adressVerification = adressVerificationList[0]
|
|
}
|
|
|
|
LOG.debug('CheckLoa: Requested role level '+ requestedRoleLevelNumber)
|
|
LOG.debug('CheckLoa: idVerification: ' + getUserAGOVLoiIdVerification())
|
|
LOG.debug('CheckLoa: adressVerification : ' + adressVerification)
|
|
|
|
def idVerificationMethodList = getUserAGOVLoiIdVerification()
|
|
|
|
session.setAttribute('idVerification', idVerificationMethodList.isEmpty() ? 'None' : idVerificationMethodList.last())
|
|
session.setAttribute('agov.adressVerification', '' + adressVerification)
|
|
|
|
|
|
if (requestedRoleLevelNumber == 0) {
|
|
// AuthnFailed_Zero_RoleLvl
|
|
response.setResult('error');
|
|
return
|
|
}
|
|
|
|
if (session.get('ch.adnovum.nevisidm.profileExtId') == '') {
|
|
LOG.error("Event='DATAERROR', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${user}, CredentialType='${credentialType}', errorMessage='Account without Profile', SourceIp=${sourceIp}, UserAgent='${userAgent}'")
|
|
|
|
session.setAttribute('contextClassRefToSet', 'urn:qa.agov.ch:names:tc:ac:classes:100')
|
|
response.setResult('ok')
|
|
return
|
|
}
|
|
|
|
// Transform sex to number
|
|
if(session.get('ch.nevis.idm.User.gender') == 'MALE'){
|
|
session.setAttribute('ch.nevis.idm.User.gender', '1')
|
|
}
|
|
if(session.get('ch.nevis.idm.User.gender') == 'FEMALE'){
|
|
session.setAttribute('ch.nevis.idm.User.gender', '2')
|
|
}
|
|
if(session.get('ch.nevis.idm.User.gender') == 'OTHER'){
|
|
session.setAttribute('ch.nevis.idm.User.gender', '3')
|
|
}
|
|
|
|
|
|
for (String role : getUserAGOVLoiRoles()) {
|
|
if (role.startsWith('level')) {
|
|
def roleLevel = role.substring(5)
|
|
int roleLevelNumber = Integer.parseInt(roleLevel)
|
|
if (highestRoleLevelNumber == 0) {
|
|
highestRoleLevelNumber = roleLevelNumber
|
|
}
|
|
if (highestRoleLevelNumber< roleLevelNumber) {
|
|
highestRoleLevelNumber=roleLevelNumber
|
|
}
|
|
}
|
|
}
|
|
LOG.debug('CheckLoa: Highest role Level' + highestRoleLevelNumber.toString() +' contextclassref' + requestedRoleLevelNumber.toString())
|
|
LOG.debug('CheckLoa: Compare' + (highestRoleLevelNumber>=requestedRoleLevelNumber))
|
|
|
|
//set attribute Actual Role Level
|
|
session.setAttribute('agov.actualRoleLevel', '' + highestRoleLevelNumber)
|
|
LOG.debug('CheckLoa: actual role level (agov) '+ highestRoleLevelNumber)
|
|
|
|
if (highestRoleLevelNumber > 0) {
|
|
// set attribute contextClassRefToSet
|
|
session.setAttribute('contextClassRefToSet','urn:qa.agov.ch:names:tc:ac:classes:' .concat(highestRoleLevelNumber.toString()))
|
|
} else {
|
|
// by default 100
|
|
session.setAttribute('contextClassRefToSet','urn:qa.agov.ch:names:tc:ac:classes:100' )
|
|
}
|
|
|
|
// 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 origIdVerification = getUserAGOVLoiIdVerification(highestRoleLevelNumber.toString()) ?: 'None'
|
|
|
|
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)
|
|
|
|
def validFrom = getUserMustRecoverValidFrom() ?: ''
|
|
session.setAttribute('agov.recovery.currentAgovAqRoleValidFrom', '' + validFrom )
|
|
|
|
LOG.debug("CheckLoa: mustRecover: origIdVerification=${origIdVerification}, idVerification=${idVerification}, currentAgovAqForRecovery=${currentAgovAqForRecovery}")
|
|
|
|
response.setResult('exit.2')
|
|
return
|
|
|
|
} else if (role == 'recovery') {
|
|
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)
|
|
|
|
response.setResult('exit.2')
|
|
return
|
|
}
|
|
}
|
|
|
|
if (highestRoleLevelNumber>=requestedRoleLevelNumber) {
|
|
|
|
// set attribute ValidFrom and ValidTo (only for higher than 100)
|
|
if (highestRoleLevelNumber > 100) {
|
|
def validFrom = getUserAGOVLoiValidFrom('level'.concat(highestRoleLevelNumber.toString()))
|
|
def validTo = getUserAGOVLoiValidTo('level'.concat(highestRoleLevelNumber.toString()))
|
|
|
|
LOG.debug('CheckLoa: ValidFrom :' + validFrom)
|
|
LOG.debug('CheckLoa: ValidTo :' + validTo)
|
|
|
|
if(validFrom != '') {
|
|
session.setAttribute('ValidFrom', '' + validFrom)
|
|
}
|
|
if(validTo != '') {
|
|
session.setAttribute('ValidTo', '' + validTo)
|
|
}
|
|
}
|
|
response.setResult('ok')
|
|
return;
|
|
} else {
|
|
// Insufficient_LoaInfo
|
|
response.setResult('exit.1');
|
|
return;
|
|
}
|
|
} catch (Exception ex) {
|
|
LOG.error("Event='DATAERROR', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${user}, CredentialType='${credentialType}', errorMessage='exception occured: ${ex}', SourceIp=${sourceIp}, UserAgent='${userAgent}'")
|
|
ex = StackTraceUtils.sanitize(ex)
|
|
def affectedLines = ex.stackTrace.findAll { it.className.startsWith('Script') }.collect { "${it.methodName}:${it.lineNumber}" }
|
|
LOG.error("FATAL: Script failure (at lines: ${affectedLines})", ex)
|
|
// AuthnFailed_Zero_RoleLvl
|
|
response.setResult('error');
|
|
return;
|
|
} |