import ch.nevis.esauth.auth.engine.AuthResponse import ch.nevis.idm.client.IdmRestClient import ch.nevis.idm.client.IdmRestClientFactory import ch.nevis.idm.client.HTTPRequestWrapper import groovy.json.JsonSlurper import groovy.xml.XmlSlurper def getHeader(String name) { def inctx = request.getLoginContext() // case-insensitive lookup of HTTP headers def map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER) map.putAll(inctx) return map['connection.HttpHeader.' + name] } // Accounting def requester = session['ch.nevis.auth.saml.request.scoping.requesterId'] ?: 'unknown' def requestId = session['ch.nevis.auth.saml.request.id'] ?: 'unknown' 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' IdmRestClient idmRestClient = IdmRestClientFactory.get(parameters) String clientExtId = session.get('ch.adnovum.nevisidm.user.clientExtId') String userExtId = session.get('ch.adnovum.nevisidm.user.extId') String mobile = session.get('ch.nevis.idm.User.mobile') String baseUrl = parameters.get('baseUrl') String endPoint = "${baseUrl}/core/v1/${clientExtId}/users/${userExtId}" if (mobile) { LOG.debug("User '${user}' has already registered a mobile number") response.setResult('done') return } def agovSkipAskingMobileCookieValue = 'missing' if (getHeader('cookie') != null) { def cookies = getHeader('cookie') if (cookies.matches('^.*agovSkipAskingMobile=([^;]+).*$')) { agovSkipAskingMobileCookieValue = cookies.replaceAll('^.*agovSkipAskingMobile=([^;]+).*$', '$1') } } if (agovSkipAskingMobileCookieValue == 'true') { // Don't aske the user again... LOG.info("Event='SKIPPEDMOBILENUMBER', Requester='${requester}', RequestId='${requestId}', User=${user}, SourceIp=${sourceIp}, UserAgent='${userAgent}'") response.setResult('done') return } if (!inargs['submit'] && (!inargs['mobile'] || !inargs['mobile'].isEmpty()) && inargs['language'] && inargs['language'] != session['ch.nevis.session.user.language']) { // language switch, nothing else to do, just display again the GUI response.setStatus(AuthResponse.AUTH_CONTINUE) return } if (inargs['submit'] && (!inargs['mobile'] || inargs['mobile'].isEmpty()) && inargs['skip'] && inargs['skip'] == 'true') { // no mobile, and user wants to skip it LOG.info("Event='NOMOBILENUMBER', Requester='${requester}', RequestId='${requestId}', User=${user}, SourceIp=${sourceIp}, UserAgent='${userAgent}'") // persistent cookie for 30d; def agovSkipAskingMobileCookie = "agovSkipAskingMobile=true; Domain=${parameters.get('cookie.domain')}; Path=/; Max-Age=2592000; SameSite=Strict; Secure; HttpOnly" // setHeader doesn't support multiple headers with the same name, so we use // a different one, and rewrite it in the proxy with Lua response.setHeader('Set-Cookie2', agovSkipAskingMobileCookie) response.setResult('done') return } if (inargs['submit'] && inargs['mobile'] && !inargs['mobile'].isEmpty()) { // IMPORTANT/haburger/2024-DEC-09: the pattern must be the same as ch.adnovum.agov.common.util.InputPatterns.PHONE_NUMBER_PATTERN if (!inargs['mobile'].replaceAll('\\s', '').matches('^(?:\\+[0-9]+)?$')) { LOG.warn("Event='MOBILEFAILED', Requester='${requester}', RequestId='${requestId}', User=${user}, SourceIp=${sourceIp}, UserAgent='${userAgent}', reason='User provided invalid number (${inargs['mobile']})'") response.setResult('done') return } String result // mobile is also stored without spaces def patchBdy = "{\"contacts\":{\"mobile\":\"${inargs['mobile'].replaceAll('\\s', '')}\"},\"modificationComment\":\"added mobile number from user during request ${requestId}\"}" try { result = idmRestClient.patch(endPoint, patchBdy) } catch(Exception e) { LOG.warn("Event='MOBILEFAILED', Requester='${requester}', RequestId='${requestId}', User=${user}, SourceIp=${sourceIp}, UserAgent='${userAgent}', reason='failed to save number (${e})'") } response.setResult('done') return } // we should ask the user response.setStatus(AuthResponse.AUTH_CONTINUE)