Skip to content

Commit

Permalink
fix(jans-linux-setup): missing code for platform authenticator (Touch…
Browse files Browse the repository at this point in the history
…ID) (#792)
  • Loading branch information
maduvena committed Feb 9, 2022
1 parent 40ca464 commit 263b76a
Showing 1 changed file with 41 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from io.jans.as.server.util import ServerUtil
from io.jans.service.cdi.util import CdiUtil
from io.jans.util import StringHelper

from java.util import Arrays
from java.util.concurrent.locks import ReentrantLock
from javax.ws.rs import ClientErrorException
from javax.ws.rs.core import Response
Expand All @@ -38,12 +38,12 @@ def init(self, customScript, configurationAttributes):
self.fido2_domain = None
if configurationAttributes.containsKey("fido2_domain"):
self.fido2_domain = configurationAttributes.get("fido2_domain").getValue2()

self.metaDataLoaderLock = ReentrantLock()
self.metaDataConfiguration = None

print "Fido2. Initialized successfully"
return True
return True

def destroy(self, configurationAttributes):
print "Fido2. Destroy"
Expand All @@ -69,6 +69,7 @@ def authenticate(self, configurationAttributes, requestParameters, step):

if step == 1:
print "Fido2. Authenticate for step 1"
identity.setWorkingParameter("platformAuthenticatorAvailable",ServerUtil.getFirstValue(requestParameters, "loginForm:platformAuthenticator"))

user_password = credentials.getPassword()
logged_in = False
Expand Down Expand Up @@ -163,6 +164,12 @@ def prepareForStep(self, configurationAttributes, requestParameters, step):
assertionService = Fido2ClientFactory.instance().createAssertionService(metaDataConfiguration)
assertionRequest = json.dumps({'username': userName}, separators=(',', ':'))
assertionResponse = assertionService.authenticate(assertionRequest).readEntity(java.lang.String)
# if device has only platform authenticator and assertion is expecting a security key
if "internal" in assertionResponse:
identity.setWorkingParameter("platformAuthenticatorAvailable", "true")
else:
identity.setWorkingParameter("platformAuthenticatorAvailable", "false")

except ClientErrorException, ex:
print "Fido2. Prepare for step 2. Failed to start assertion flow. Exception:", sys.exc_info()[1]
return False
Expand All @@ -171,7 +178,20 @@ def prepareForStep(self, configurationAttributes, requestParameters, step):

try:
attestationService = Fido2ClientFactory.instance().createAttestationService(metaDataConfiguration)
attestationRequest = json.dumps({'username': userName, 'displayName': userName, 'attestation': 'direct'}, separators=(',', ':'))
platformAuthenticatorAvailable = identity.getWorkingParameter("platformAuthenticatorAvailable") == "true"
basic_json = {'username': userName, 'displayName': userName, 'attestation' : 'direct'}
print "% s" % identity.getWorkingParameter("platformAuthenticatorAvailable")
if platformAuthenticatorAvailable is True:
# the reason behind userVerification = discouraged --> https://chromium.googlesource.com/chromium/src/+/master/content/browser/webauth/uv_preferred.md
platform_json = {"authenticatorSelection":{"authenticatorAttachment":"platform","requireResidentKey" : "false", "userVerification" : "discouraged" } }
basic_json.update(platform_json)

# also need to add this --> excludeCredentials : [//registered ids]
print " basic_json %s" % basic_json

attestationRequest = json.dumps(basic_json)
#, separators=(',', ':'))

attestationResponse = attestationService.register(attestationRequest).readEntity(java.lang.String)
except ClientErrorException, ex:
print "Fido2. Prepare for step 2. Failed to start attestation flow. Exception:", sys.exc_info()[1]
Expand All @@ -190,7 +210,7 @@ def prepareForStep(self, configurationAttributes, requestParameters, step):
return False

def getExtraParametersForStep(self, configurationAttributes, step):
return None
return Arrays.asList( "platformAuthenticatorAvailable")

def getCountAuthenticationSteps(self, configurationAttributes):
return 2
Expand All @@ -199,27 +219,32 @@ def getNextStep(self, configurationAttributes, requestParameters, step):
return -1

def getPageForStep(self, configurationAttributes, step):
if step == 2:
return "/auth/fido2/login.xhtml"

if step == 1:
return "/auth/fido2/step1.xhtml"
elif step == 2:
identity = CdiUtil.bean(Identity)
if identity.getWorkingParameter("platformAuthenticatorAvailable") == "true":
return "/auth/fido2/platform.xhtml"
else:
return "/auth/fido2/secKeys.xhtml"
return ""

def logout(self, configurationAttributes, requestParameters):
return True

def getAuthenticationMethodClaims(self, requestParameters):
return None

def getLogoutExternalUrl(self, configurationAttributes, requestParameters):
print "Get external logout URL call"
return None
return None

def getMetaDataConfiguration(self):
if self.metaDataConfiguration != None:
return self.metaDataConfiguration

self.metaDataLoaderLock.lock()
# Make sure that another thread not loaded configuration already
# Make sure that another thread not loaded configuration already
if self.metaDataConfiguration != None:
return self.metaDataConfiguration

Expand All @@ -228,7 +253,7 @@ def getMetaDataConfiguration(self):
self.fido2_server_metadata_uri = self.fido2_server_uri + "/.well-known/fido2-configuration"

metaDataConfigurationService = Fido2ClientFactory.instance().createMetaDataConfigurationService(self.fido2_server_metadata_uri)

max_attempts = 10
for attempt in range(1, max_attempts + 1):
try:
Expand All @@ -238,7 +263,7 @@ def getMetaDataConfiguration(self):
# Detect if last try or we still get Service Unavailable HTTP error
if (attempt == max_attempts) or (ex.getResponse().getResponseStatus() != Response.Status.SERVICE_UNAVAILABLE):
raise ex

java.lang.Thread.sleep(3000)
print "Attempting to load metadata: %d" % attempt
finally:
Expand Down

0 comments on commit 263b76a

Please sign in to comment.