diff --git a/patterns/1f0702aaabef60a615abf41f_resources/resources.zip b/patterns/1f0702aaabef60a615abf41f_resources/resources.zip index 8a6582a..f7d8c0c 100644 Binary files a/patterns/1f0702aaabef60a615abf41f_resources/resources.zip and b/patterns/1f0702aaabef60a615abf41f_resources/resources.zip differ diff --git a/patterns/204c22beaccdfd22727af378_labels/labels.zip b/patterns/204c22beaccdfd22727af378_labels/labels.zip index 546b2f4..87b170b 100644 Binary files a/patterns/204c22beaccdfd22727af378_labels/labels.zip and b/patterns/204c22beaccdfd22727af378_labels/labels.zip differ diff --git a/patterns/204c22beaccdfd22727af378_template/webdata.zip b/patterns/204c22beaccdfd22727af378_template/webdata.zip index cbb9a7a..74ecdc0 100644 Binary files a/patterns/204c22beaccdfd22727af378_template/webdata.zip and b/patterns/204c22beaccdfd22727af378_template/webdata.zip differ diff --git a/patterns/302b0fa3c5c3d1d17e9b1004_resources/fido2_auth.groovy b/patterns/302b0fa3c5c3d1d17e9b1004_resources/fido2_auth.groovy index a98babe..2ff5745 100644 --- a/patterns/302b0fa3c5c3d1d17e9b1004_resources/fido2_auth.groovy +++ b/patterns/302b0fa3c5c3d1d17e9b1004_resources/fido2_auth.groovy @@ -98,9 +98,12 @@ if (path == '/nevisfido/fido2/attestation/options') { } post(connection, json) def responseCode = connection.responseCode + def responseText = responseCode == 200 ? connection.inputStream.text : '{"allowCredentials":[]}' + def jsonResponse = new JsonSlurper().parseText(responseText) + def numOfKeys = jsonResponse.allowCredentials ? jsonResponse.allowCredentials.size() : 0 - // non existing account, or account without FIDO2 key case - if (responseCode == 404 || responseCode == 400) { + // non existing account, account without FIDO2 key , or account with disabled FIDO2 key case + if (responseCode == 404 || responseCode == 400 || numOfKeys == 0) { LOG.debug("Fido2Auth: <== Response: ${responseCode}") @@ -113,36 +116,36 @@ if (path == '/nevisfido/fido2/attestation/options') { 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 tAuth = System.currentTimeMillis() - (request.getSession(true).getCreationTime().getEpochSecond() * 1000) + def details = "no account (404)" + if (responseCode == 400 ) { + details = "no fido2 keys for account (400)" + } else if (responseCode == 200) { + details = "no active fido2 key for account (200, empty allowCredentials array)" + } - LOG.info("Event='NOACCOUNT', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${session['ch.nevis.idm.User.email']}, CredentialType='${credentialType}', tAuth=${tAuth}ms, SourceIp=${sourceIp}, UserAgent='${userAgent}'") + LOG.info("Event='NOACCOUNT', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${session['ch.nevis.idm.User.email']}, CredentialType='${credentialType}', tAuth=${tAuth}ms, SourceIp=${sourceIp}, UserAgent='${userAgent}', Details='${details}'") + // returning a fake options structure, which shouldn't leak whether the user account exists or not // keyId is unique per environment and email, fido2SessionId and challenge are renewed each time def keyId = UUID.nameUUIDFromBytes("${parameters['rpId']}.${session['ch.nevis.idm.User.email']}".getBytes()) - def responseText = """{"status": "ok", - "errorMessage": "", - "fido2SessionId": "${UUID.randomUUID()}", - "challenge": "${base64url(UUID.randomUUID())}", - "timeout": 300000, - "rpId": "${parameters['rpId']}", - "allowCredentials": [ - { - "type": "public-key", - "id": "${base64url(keyId)}", - "transports": [] - } - ], - "userVerification": "required"}""" - - response.setContent(responseText) // return response from nevisFIDO "as-is" - response.setContentType('application/json') - response.setHttpStatusCode(200) - response.setIsDirectResponse(true) - return + responseText = """{"status": "ok", + "errorMessage": "", + "fido2SessionId": "${UUID.randomUUID()}", + "challenge": "${base64url(UUID.randomUUID())}", + "timeout": 300000, + "rpId": "${parameters['rpId']}", + "allowCredentials": [ + { + "type": "public-key", + "id": "${base64url(keyId)}", + "transports": [] + } + ], + "userVerification": "required"}""" } - def responseText = connection.inputStream.text LOG.debug("Fido2Auth: <== Response: ${responseCode} : ${responseText}") - response.setContent(responseText) // return response from nevisFIDO "as-is" + response.setContent(responseText) response.setContentType('application/json') response.setHttpStatusCode(200) response.setIsDirectResponse(true) diff --git a/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip b/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip index 546b2f4..87b170b 100644 Binary files a/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip and b/patterns/4fcfadb4a5c946ead7e6e995_labels/labels.zip differ diff --git a/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip b/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip index cbb9a7a..74ecdc0 100644 Binary files a/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip and b/patterns/4fcfadb4a5c946ead7e6e995_template/webdata.zip differ