import ch.nevis.esauth.auth.engine.AuthResponse import groovy.xml.XmlSlurper // AGOVaq conversion def minLoiRoleToCtxClssConvertorMap = [ "level100": "urn:qa.agov.ch:names:tc:ac:classes:100", "level200": "urn:qa.agov.ch:names:tc:ac:classes:200", "level300": "urn:qa.agov.ch:names:tc:ac:classes:300", "level400": "urn:qa.agov.ch:names:tc:ac:classes:400", "level500": "urn:qa.agov.ch:names:tc:ac:classes:500" ] def cleanSession() { def s = request.getAuthSession(true) s.removeAttribute('agov.op.onboarding.ctxClass') s.removeAttribute('agov.op.onboarding.minLoi') s.removeAttribute('agov.op.onboarding.homeName') s.removeAttribute('agov.op.onboarding.subject') s.removeAttribute('agov.op.onboarding.process.state') s.removeAttribute('ch.adnovum.nevisidm.userDto') s.removeAttribute('saml.response.statusCode') if (response.getActualRoles().length > 0) { def actualRoles = Arrays.copyOf(response.getActualRoles(), response.getActualRoles().length) actualRoles.each{ role -> response.removeActualRole(role) } } } // for autditing def user = session['ch.adnovum.nevisidm.user.extId'] ?: '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' def minLoi = 'unknown' // 1) makes sure, that we are or were invoked with a correct URL ticket, set error code, if not if (inargs['cd'] == null && session['agov.op.onboarding.code'] == null) { response.setNote('lasterror', '9901') response.setNote('lasterrorinfo', 'valid on-boarding link required') } // 2a) if code as query param, store it to the session, and redirect if (inargs['cd'] != null) { // make sure, we are clean to be able to start over cleanSession() response.setSessionAttribute('agov.op.onboarding.code', inargs['cd']) response.setStatus(AuthResponse.AUTH_CONTINUE) response.setTransferDestination('/AUTH/ONBOARDING/') response.setIsRedirectTransfer(true) return } // 2b) clean the url, if necessary if (request.currentResource.replaceAll('^https:\\/\\/[^\\/]+\\/AUTH\\/ONBOARDING\\/', '').length() > 0) { if (inargs['language'] && inargs['language'] != session['ch.nevis.session.user.language']) { // language change, set the language cookie def langCookie = "LANG=${inargs['language']}; Domain=${parameters.get('cookie.domain')}; Path=/" response.setHeader('Set-Cookie', langCookie) } response.setStatus(AuthResponse.AUTH_CONTINUE) response.setTransferDestination('/AUTH/ONBOARDING/') response.setIsRedirectTransfer(true) return } // 3) if SAMLResponse available, process it if (inargs['SAMLResponse'] != null) { // we don't use a RelayState, make sure he is ignored request.getInArgs().remove("RelayState") response.setResult('processResponse') return } // 4) check if we could already validate the ticket, and load the user if (session['ch.adnovum.nevisidm.userDto'] != null && notes['lasterror'] == null) { try { def userDto = new XmlSlurper().parseText(session['ch.adnovum.nevisidm.userDto']) def userState = userDto.state if (userState == 'ACTIVE') { def minLoiList = userDto.'**'.findAll { node -> node.name() == 'roles' && node.applicationName.text() == 'OP-MinLoi' }.collect({ node -> node.name.text() }).sort() minLoi = minLoiList.isEmpty() ? null : minLoiList.first() if (minLoi != null) { response.setSessionAttribute('agov.op.onboarding.minLoi', minLoi) if (minLoiRoleToCtxClssConvertorMap.containsKey(minLoi)) { response.setSessionAttribute('agov.op.onboarding.ctxClass', minLoiRoleToCtxClssConvertorMap[minLoi]) } else { LOG.warn("OP-ONBOARDING: Failed to convert '${minLoi}' to AGOVaq, taking 'urn:qa.agov.ch:names:tc:ac:classes:100'") response.setSessionAttribute('agov.op.onboarding.ctxClass', "urn:qa.agov.ch:names:tc:ac:classes:100") } } else { LOG.debug("OP-ONBOARDING: no 'OP-MinLoi'-role assigned to user ${user}, using AGOVaq100") minLoi = "level100" response.setSessionAttribute('agov.op.onboarding.minLoi', "level100") response.setSessionAttribute('agov.op.onboarding.ctxClass', "urn:qa.agov.ch:names:tc:ac:classes:100") } LOG.info("Event='OP-AUTHNREQ', RequestedAq='${minLoi}', User=${user}, SourceIp=${sourceIp}, UserAgent=${userAgent}") response.setResult('sendAuthnRequest') } else { // state != ACTIVE and no lasterror should not happen LOG.error("On boarding ticket processing failed: state='${userState}' but not lasterror set") response.setNote('lasterror', '9909') response.setNote('lasterrorinfo', 'internal error') } } catch (Exception e) { LOG.error("On boarding ticket processing failed: Exception " + e) response.setNote('lasterror', '9909') response.setNote('lasterrorinfo', 'internal error') } } // 5) validate URL Ticket? if (inargs['submit'] != null && notes['verifyTicket'] == null) { response.setNote('verifyTicket', 'go') response.setResult('verifyTicket') return } // 6) if we reach that point, display the GUI if (response.getNote('lasterror') != null) { minLoi = session['agov.op.onboarding.minLoi'] ?: 'unknown' LOG.info("Event='OP-FAILED', RequestedAq='${minLoi}', User=${user}, SourceIp=${sourceIp}, UserAgent=${userAgent}, lasterror=${response.getNote('lasterror')}, lasterrorinfo='${response.getNote('lasterrorinfo')}'") cleanSession() } response.setStatus(AuthResponse.AUTH_CONTINUE)