def prepareForStep(self, configurationAttributes, requestParameters, step): print "U2F. prepareForStep called for step %s" % step identity = CdiUtil.bean(Identity) if (step == 1): session_id = CdiUtil.bean( SessionIdService).getSessionIdFromCookie() if StringHelper.isEmpty(session_id): print "U2F. Prepare for step 1. Failed to determine session_id" return False authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if (user == None): print "U2F. Prepare for step 1. Failed to determine user name" return False u2f_application_id = configurationAttributes.get( "u2f_application_id").getValue2() # Check if user have registered devices deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) userInum = user.getAttribute("inum") registrationRequest = None authenticationRequest = None deviceRegistrations = deviceRegistrationService.findUserDeviceRegistrations( userInum, u2f_application_id) if (deviceRegistrations.size() > 0): print "U2F. Prepare for step 1. Call FIDO U2F in order to start authentication workflow" try: authenticationRequestService = FidoU2fClientFactory.instance( ).createAuthenticationRequestService( self.metaDataConfiguration) authenticationRequest = authenticationRequestService.startAuthentication( user.getUserId(), None, u2f_application_id, session_id) except ClientResponseFailure, ex: if (ex.getResponse().getResponseStatus() != Response.Status.NOT_FOUND): print "U2F. Prepare for step 1. Failed to start authentication workflow. Exception:", sys.exc_info( )[1] return False else: print "U2F. Prepare for step 1. Call FIDO U2F in order to start registration workflow" registrationRequestService = FidoU2fClientFactory.instance( ).createRegistrationRequestService(self.metaDataConfiguration) registrationRequest = registrationRequestService.startRegistration( user.getUserId(), u2f_application_id, session_id) identity.setWorkingParameter( "fido_u2f_authentication_request", ServerUtil.asJson(authenticationRequest)) identity.setWorkingParameter( "fido_u2f_registration_request", ServerUtil.asJson(registrationRequest)) return True
def prepareForStep(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) if (step == 1): return True elif (step == 2): print "U2F. Prepare for step 2" session_id = CdiUtil.bean(SessionIdService).getSessionIdFromCookie() if StringHelper.isEmpty(session_id): print "U2F. Prepare for step 2. Failed to determine session_id" return False authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if (user == None): print "U2F. Prepare for step 2. Failed to determine user name" return False u2f_application_id = configurationAttributes.get("u2f_application_id").getValue2() # Check if user have registered devices deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) userInum = user.getAttribute("inum") registrationRequest = None authenticationRequest = None deviceRegistrations = deviceRegistrationService.findUserDeviceRegistrations(userInum, u2f_application_id) if (deviceRegistrations.size() > 0): print "U2F. Prepare for step 2. Call FIDO U2F in order to start authentication workflow" try: authenticationRequestService = FidoU2fClientFactory.instance().createAuthenticationRequestService(self.metaDataConfiguration) authenticationRequest = authenticationRequestService.startAuthentication(user.getUserId(), None, u2f_application_id, session_id) except ClientResponseFailure, ex: if (ex.getResponse().getResponseStatus() != Response.Status.NOT_FOUND): print "U2F. Prepare for step 2. Failed to start authentication workflow. Exception:", sys.exc_info()[1] return False else: print "U2F. Prepare for step 2. Call FIDO U2F in order to start registration workflow" registrationRequestService = FidoU2fClientFactory.instance().createRegistrationRequestService(self.metaDataConfiguration) registrationRequest = registrationRequestService.startRegistration(user.getUserId(), u2f_application_id, session_id) identity.setWorkingParameter("fido_u2f_authentication_request", ServerUtil.asJson(authenticationRequest)) identity.setWorkingParameter("fido_u2f_registration_request", ServerUtil.asJson(registrationRequest)) return True
def prepareFidoAuthentication(self, username, identity): authenticationRequestService = FidoU2fClientFactory.instance().createAuthenticationRequestService(self.metaDataConfiguration) session = identity.getSessionId() identity.getSessionId().getSessionAttributes().put(Constants.AUTHENTICATED_USER, username) authenticationRequest = authenticationRequestService.startAuthentication(username, None, self.u2fApplicationId, session.getId()) identity.setWorkingParameter("fido_u2f_authentication_request", ServerUtil.asJson(authenticationRequest))
class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, customScript, configurationAttributes): print "Fido2. Initialization" if not configurationAttributes.containsKey("fido2_server_uri"): print "fido2_server_uri. Initialization. Property fido2_server_uri is not specified" return False self.fido2_server_uri = configurationAttributes.get( "fido2_server_uri").getValue2() #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 def destroy(self, configurationAttributes): print "Fido2. Destroy" print "Fido2. Destroyed successfully" return True def getApiVersion(self): return 11 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() if (step == 1): print "Fido2. Authenticate for step 1" if authenticationService.getAuthenticatedUser() != None: return True user_password = credentials.getPassword() logged_in = False if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): userService = CdiUtil.bean(UserService) logged_in = authenticationService.authenticate( user_name, user_password) if (not logged_in): return False return True elif (step == 2): print "Fido2. Authenticate for step 2" token_response = ServerUtil.getFirstValue(requestParameters, "tokenResponse") if token_response == None: print "Fido2. Authenticate for step 2. tokenResponse is empty" return False auth_method = ServerUtil.getFirstValue(requestParameters, "authMethod") if auth_method == None: print "Fido2. Authenticate for step 2. authMethod is empty" return False authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if (user == None): print "Fido2. Prepare for step 2. Failed to determine user name" return False if (auth_method == 'authenticate'): print "Fido2. Prepare for step 2. Call Fido2 in order to finish authentication flow" assertionService = Fido2ClientFactory.instance( ).createAssertionService(self.metaDataConfiguration) assertionStatus = assertionService.verify(token_response) authenticationStatusEntity = assertionStatus.readEntity( java.lang.String) if (assertionStatus.getStatus() != Response.Status.OK.getStatusCode()): print "Fido2. Authenticate for step 2. Get invalid authentication status from Fido2 server" return False return True elif (auth_method == 'enroll'): print "Fido2. Prepare for step 2. Call Fido2 in order to finish registration flow" attestationService = Fido2ClientFactory.instance( ).createAttestationService(self.metaDataConfiguration) attestationStatus = attestationService.verify(token_response) if (attestationStatus.getStatus() != Response.Status.OK.getStatusCode()): print "Fido2. Authenticate for step 2. Get invalid registration status from Fido2 server" return False return True else: print "Fido2. Prepare for step 2. Authentication method is invalid" return False return False else: return False def prepareForStep(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) if (step == 1): return True elif (step == 2): print "Fido2. Prepare for step 2" session_id = CdiUtil.bean( SessionIdService).getSessionIdFromCookie() if StringHelper.isEmpty(session_id): print "Fido2. Prepare for step 2. Failed to determine session_id" return False authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if (user == None): print "Fido2. Prepare for step 2. Failed to determine user name" return False userName = user.getUserId() metaDataConfiguration = self.getMetaDataConfiguration() # Check if user have registered devices registrationPersistenceService = CdiUtil.bean( RegistrationPersistenceService) assertionResponse = None attestationResponse = None userFido2Devices = registrationPersistenceService.findAllRegisteredByUsername( userName) if (userFido2Devices.size() > 0): print "Fido2. Prepare for step 2. Call Fido2 endpoint in order to start assertion flow" try: assertionService = Fido2ClientFactory.instance( ).createAssertionService(metaDataConfiguration) assertionRequest = json.dumps({'username': userName}, separators=(',', ':')) assertionResponse = assertionService.authenticate( assertionRequest).readEntity(java.lang.String) except ClientResponseFailure, ex: print "Fido2. Prepare for step 2. Failed to start assertion flow. Exception:", sys.exc_info( )[1] return False else: print "Fido2. Prepare for step 2. Call Fido2 endpoint in order to start attestation flow" try: attestationService = Fido2ClientFactory.instance( ).createAttestationService(metaDataConfiguration) attestationRequest = json.dumps( { 'username': userName, 'displayName': userName }, separators=(',', ':')) attestationResponse = attestationService.register( attestationRequest).readEntity(java.lang.String) except ClientResponseFailure, ex: print "Fido2. Prepare for step 2. Failed to start attestation flow. Exception:", sys.exc_info( )[1] return False identity.setWorkingParameter("fido2_assertion_request", ServerUtil.asJson(assertionResponse)) identity.setWorkingParameter( "fido2_attestation_request", ServerUtil.asJson(attestationResponse)) print "Fido2. Prepare for step 2. Successfully start flow with next requests.\nfido2_assertion_request: '%s'\nfido2_attestation_request: '%s'" % ( assertionResponse, attestationResponse) return True
def prepareForStep(self, configurationAttributes, requestParameters, step): if REMOTE_DEBUG: pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True) # Inject dependencies identity = CdiUtil.bean(Identity) facesResources = CdiUtil.bean(FacesResources) facesService = CdiUtil.bean(FacesService) userService = CdiUtil.bean(UserService) session = identity.getSessionId() sessionAttributes = session.getSessionAttributes() externalContext = facesResources.getFacesContext().getExternalContext() uiLocales = sessionAttributes.get(AuthorizeRequestParam.UI_LOCALES) rpConfig = self.getRPConfig(session) clientUri = self.getClientUri(session) externalContext.addResponseHeader( "Content-Security-Policy", "default-src 'self' https://www.canada.ca; font-src 'self' https://fonts.gstatic.com https://use.fontawesome.com https://www.canada.ca; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline' https://use.fontawesome.com https://fonts.googleapis.com https://www.canada.ca; script-src 'self' 'unsafe-inline' https://www.canada.ca https://ajax.googleapis.com; connect-src 'self' https://*.fjgc-gccf.gc.ca" ) if step == 1: httpRequest = externalContext.getRequest() # Bookmark detection #if httpRequest.getHeader("referer") is None: # if StringHelper.isNotEmpty(clientUri): # facesService.redirectToExternalURL(clientUri) # return True # else: # print("%s: prepareForStep. clientUri is missing for client %s" % (self.name, self.getClient(session).getClientName())) # return False # forceAuthn workaround prompt2 = httpRequest.getParameter("prompt2") if prompt2 == "login": identity.setWorkingParameter("forceAuthn", True) # step could actually be 2, or 3 if uiLocales is not None: if len(self.providers) > 1: step = self.STEP_CHOOSER else: step = self.STEP_1FA if identity.getWorkingParameter("abort"): # Back button workaround # Obtain the client URI of the current client from the client configuration if len(self.providers ) == 1: # Pass through, so send them back to the client if StringHelper.isNotEmpty(clientUri): facesService.redirectToExternalURL(clientUri) return True else: print( "%s: prepareForStep. clientUri is missing for client %s" % (self.name, self.getClient(session).getClientName())) return False else: # reset the chooser identity.setWorkingParameter("provider", None) if step == self.STEP_CHOOSER: # Prepare for chooser page customization. for param in ["layout", "chooser", "content"]: identity.setWorkingParameter(param, rpConfig[param]) elif step in {self.STEP_1FA, self.STEP_COLLECT, self.STEP_2FA}: # Passport passportOptions = { "ui_locales": uiLocales, "exp": int(time.time()) + 60 } if step in {self.STEP_1FA, self.STEP_COLLECT}: provider = identity.getWorkingParameter("provider") if provider is None and len( self.providers ) == 1: # Only one provider. Direct Pass-through provider = next(iter(self.providers)) identity.setWorkingParameter("provider", provider) if step == self.STEP_1FA: # Coordinate single-sign-on (SSO) maxAge = (sessionAttributes.get(AuthorizeRequestParam.MAX_AGE) or self.getClient(session).getDefaultMaxAge()) if (identity.getWorkingParameter("forceAuthn") or ("GCCF" in self.passport.getProvider(provider)["options"] and maxAge < 1200) ): # 1200 is 20 minutes, the SSO timeout on GCKey and CBS passportOptions["forceAuthn"] = "true" elif step == self.STEP_COLLECT: collect = rpConfig.get("collect") if collect is not None: passportOptions["allowCreate"] = rpConfig.get( "allowCreate") or "false" passportOptions["spNameQualifier"] = collect else: # This should never happen print( "%s. prepareForStep: collection entityID is missing" % self.name) return False elif step == self.STEP_2FA: provider = rpConfig.get("mfaProvider") if provider is None: print("%s: prepareForStep. mfaProvider is missing!" % self.name) return False mfaId = identity.getWorkingParameter("mfaId") if mfaId is None: print("%s: prepareForStep. mfaId is missing!" % self.name) return False else: passportOptions["login_hint"] = mfaId # The following parameters are redundant, but currently required by the 2ndFaaS passportOptions[ "redirect_uri"] = self.passport.getProvider( provider)["callbackUrl"] passportOptions["response_type"] = "code" passportOptions["scope"] = "openid profile" # Set the abort flag to handle back button identity.setWorkingParameter("abort", True) # Send the request to passport passportRequest = self.passport.createRequest( provider, passportOptions) facesService.redirectToExternalURL(passportRequest) elif step in {self.STEP_FIDO_REGISTER, self.STEP_FIDO_AUTH}: userId = identity.getWorkingParameter("userId") metaDataConfiguration = self.getFidoMetaDataConfiguration() if step == self.STEP_FIDO_REGISTER: try: attestationService = Fido2ClientFactory.instance( ).createAttestationService(metaDataConfiguration) attestationRequest = json.dumps( { 'username': userId, 'displayName': userId, 'attestation': 'direct', 'timeout': 120000, 'userVerification': 'discouraged' }, separators=(',', ':')) attestationResponse = attestationService.register( attestationRequest).readEntity(java.lang.String) except ClientErrorException as ex: print( "%s. Prepare for step. Failed to start FIDO2 attestation flow. Exception:" % self.name, sys.exc_info()[1]) return False identity.setWorkingParameter( "fido2_attestation_request", ServerUtil.asJson(attestationResponse)) print(ServerUtil.asJson(attestationResponse)) elif step == self.STEP_FIDO_AUTH: userId = identity.getWorkingParameter("userId") metaDataConfiguration = self.getFidoMetaDataConfiguration() fidoDeviceCount = userService.countFidoAndFido2Devices( userId, self.fido2_domain) try: assertionService = Fido2ClientFactory.instance( ).createAssertionService(metaDataConfiguration) assertionRequest = json.dumps( { 'username': userId, 'timeout': 120000, 'userVerification': 'discouraged' }, separators=(',', ':')) assertionResponse = assertionService.authenticate( assertionRequest).readEntity(java.lang.String) except ClientErrorException as ex: print( "%s. Prepare for step. Failed to start FIDO2 assertion flow. Exception:" % self.name, sys.exc_info()[1]) return False identity.setWorkingParameter( "fido2_assertion_request", ServerUtil.asJson(assertionResponse)) return True