BUNDBITBK-4260: improved mobile number processing

This commit is contained in:
haburger 2025-01-20 17:35:39 +00:00
parent 696596634a
commit ee73ecc9b9
9 changed files with 68 additions and 32 deletions

View File

@ -50,9 +50,9 @@
<property name="condition:loginFactorYes" value="${inargs:continue}==yes"/>
<property name="condition:loginFactorNo" value="${inargs:continue}==no"/>
</AuthState>
<AuthState name="${state.entry}_reasonSelection" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="true" resumeState="true">
<AuthState name="${state.entry}_reasonSelection" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="true" resumeState="true">
<ResultCond name="cancel" next="${state.entry}_loginFactorQuestion"/>
<ResultCond name="validReasons" next="${state.entry}_saveReason"/>
<ResultCond name="validReasons" next="${state.entry}_instructions"/>
<ResultCond name="invalidReasons" next="${state.entry}_noRecovery"/>
<Response value="AUTH_CONTINUE">
<Gui name="recovery_questionnaire_reason_selection">
@ -64,14 +64,7 @@
<GuiElem name="continue" type="submit" label="submit.button.label" value="submit"/>
</Gui>
</Response>
<property name="condition:cancel" value="${inargs:cancel}==cancel"/>
<property name="condition:validReasons" value="${inargs:continue}==yes"/>
<property name="condition:invalidReasons" value="${inargs:continue}==no"/>
</AuthState>
<AuthState name="${state.entry}_saveReason" class="ch.nevis.esauth.auth.states.standard.TransformAttributes" final="false" resumeState="false">
<ResultCond name="default" next="${state.entry}_instructions"/>
<Response value="AUTH_CONTINUE"/>
<property name="sess:agov.recovery.reason" value="${inargs:reason}"/>
<property name="script" value="file:///var/opt/nevisauth/default/conf/questionnaireReasonProcessing.groovy"/>
</AuthState>
<AuthState name="${state.entry}_instructions" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="true" resumeState="true">
<ResultCond name="cancel" next="${state.entry}_loginFactorQuestion"/>
@ -88,7 +81,7 @@
<property name="condition:continue" value="${inargs:continue}==continue"/>
</AuthState>
<AuthState name="${state.entry}_noRecovery" class="ch.nevis.esauth.auth.states.standard.ConditionalDispatcherState" final="true" resumeState="true">
<ResultCond name="cancel" next="${state.exit.2}"/>
<ResultCond name="cancel" next="${state.entry}_logReason"/>
<Response value="AUTH_CONTINUE">
<Gui name="recovery_questionnaire_no_recovery">
<GuiElem name="intro" type="info" label="recovery.intro.message"/>
@ -98,6 +91,15 @@
</Response>
<property name="condition:cancel" value="${inargs:cancel}==cancel"/>
</AuthState>
<AuthState name="${state.entry}_logReason" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="false" resumeState="false">
<ResultCond name="ok" next="${state.exit.2}"/>
<Response value="AUTH_CONTINUE">
<Gui name="not_used"/>
</Response>
<property name="scriptTraceGroup" value="AGOV-ACCT"/>
<!-- Script is manged with pattern Recovery_createURLTicket -->
<property name="script" value="file:///var/opt/nevisauth/default/conf/logRecoveryReason.groovy"/>
</AuthState>
<AuthState name="${state.entry}_enterEmail" class="ch.nevis.esauth.auth.states.scripting.ScriptState" final="true" resumeState="true">
<ResultCond name="cancel" next="${state.exit.2}"/>
<ResultCond name="verifyEmail" next="${state.entry}_saveEmail"/>

View File

@ -0,0 +1,24 @@
import ch.nevis.esauth.auth.engine.AuthResponse
if (inargs['reason']) {
response.setSessionAttribute('agov.recovery.reason', '' + inargs['reason'])
}
if (inargs['cancel'] && inargs['cancel'] == 'cancel') {
response.setResult('cancel')
return
}
if (inargs['continue'] && inargs['continue'] == 'yes') {
response.setResult('validReasons')
return
}
if (inargs['continue'] && inargs['continue'] == 'no') {
response.setResult('invalidReasons')
return
}
// if we reach this, display the GUI again
response.setStatus(AuthResponse.AUTH_CONTINUE)
return

View File

@ -60,16 +60,19 @@ if (!inargs['submit'] && (!inargs['mobile'] || !inargs['mobile'].isEmpty()) && i
return
}
if (inargs['submit'] && (!inargs['mobile'] || inargs['mobile'].isEmpty()) && inargs['skip'] && inargs['skip'] == 'true') {
if (inargs['submit'] && (!inargs['mobile'] || inargs['mobile'].isEmpty()) && inargs['skip']) {
// no mobile, and user wants to skip it
LOG.info("Event='NOMOBILENUMBER', Requester='${requester}', RequestId='${requestId}', User=${user}, SourceIp=${sourceIp}, UserAgent='${userAgent}'")
LOG.info("Event='NOMOBILENUMBER', Requester='${requester}', RequestId='${requestId}', User=${user}, SourceIp=${sourceIp}, UserAgent='${userAgent}', Persistent='${ inargs['skip'] == 'persistent' ? true : false }'")
// 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)
if (inargs['skip'] == 'persistent') {
// 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
}

View File

@ -1,7 +1,7 @@
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 ch.nevis.esauth.util.httpclient.api.HttpClient
import io.opentelemetry.api.trace.Span
import groovy.json.JsonSlurper
import groovy.xml.XmlSlurper
@ -19,7 +19,9 @@ def userAgent = request.getLoginContext()['connection.HttpHeader.user-agent'] ?:
IdmRestClient idmRestClient = IdmRestClientFactory.get(parameters)
HttpClient httpClient = HttpClients.create(parameters)
def spanCtxt = Span.current().getSpanContext()
def traceparent = "00-${spanCtxt.getTraceId()}-${spanCtxt.getSpanId()}-${spanCtxt.getTraceFlags().asHex()}"
String clientExtId = session.get('ch.adnovum.nevisidm.user.clientExtId')
String userExtId = session.get('ch.adnovum.nevisidm.user.extId')
@ -65,21 +67,26 @@ if (outargs.containsKey('out.JWTToken')) {
if (!session['agov.new.recovery.code.generated']) {
inargs.remove('submit')
try {
def postRequest = new HTTPRequestWrapper()
postRequest.addToHeaders('Content-Type', ['application/json'])
def httpResponse = Http.post()
.url(endPoint)
.header("Accept", "application/json")
.header("traceparent", traceparent)
.entity(Http.entity()
.content("{\"userExtId\":\"$userExtId\",\"userSessionId\": \"$sessionId\"}")
.contentType("application/json")
.build())
.build()
.send(httpClient)
postRequest.setPayLoad("{\"userExtId\":\"$userExtId\",\"userSessionId\": \"$sessionId\"}".getBytes('UTF-8'))
def result = idmRestClient.postWithResponse(endPoint, postRequest)
if (result.getStatusCode() != 200) {
LOG.debug("Payload: ${new String(postRequest.getPayLoad())}")
LOG.debug("Result: ${result}")
LOG.warn("Event='RCVRY-CODE', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${user}, CredentialType='${credentialType}', SourceIp=${sourceIp}, UserAgent='${userAgent}', reason='Failed to create code (http status code ${result.getStatusCode()})")
if (httpResponse.code() != 200) {
LOG.debug("Result: ${httpResponse}")
LOG.warn("Event='RCVRY-CODE', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${user}, CredentialType='${credentialType}', SourceIp=${sourceIp}, UserAgent='${userAgent}', reason='Failed to create code (http status code ${httpResponse.code()})")
response.setResult('failed')
return
}
def json = new JsonSlurper().parseText(new String(result.getPayLoad(), 'UTF-8'))
def json = new JsonSlurper().parseText(httpResponse.bodyAsString())
notes.setProperty('agov.new.recovery.code', json['recoveryCode']['code'].replaceAll('^(....)(....)(.*)$', '$1-$2-$3'))
LOG.debug("agov.new.recovery.code: ${notes['agov.new.recovery.code']}")