def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) userService = CdiUtil.bean(UserService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() if step == 1: print "Basic (with password update). Authenticate for step 1" user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): logged_in = authenticationService.authenticate(user_name, user_password) if not logged_in: return False find_user_by_uid = authenticationService.getAuthenticatedUser() user_expDate = find_user_by_uid.getAttribute("oxPasswordExpirationDate", False) if user_expDate == None: print "Basic (with password update). Authenticate for step 1. User has no oxPasswordExpirationDate date" return False dt = StaticUtils.decodeGeneralizedTime(user_expDate) # Get Current Date calendar = GregorianCalendar(TimeZone.getTimeZone("UTC")); now = calendar.getTime() if now.compareTo(dt) > 0: # Add 90 Days to current date calendar.setTime(now) calendar.add(calendar.DATE, 1) dt_plus_90 = calendar.getTime() expDate = StaticUtils.encodeGeneralizedTime(dt_plus_90) identity.setWorkingParameter("expDate", expDate) return True elif step == 2: print "Basic (with password update). Authenticate for step 2" user = authenticationService.getAuthenticatedUser() if user == None: print "Basic (with password update). Authenticate for step 2. Failed to determine user name" return False user_name = user.getUserId() find_user_by_uid = userService.getUser(user_name) newExpDate = identity.getWorkingParameter("expDate") if find_user_by_uid == None: print "Basic (with password update). Authenticate for step 2. Failed to find user" return False print "Basic (with password update). Authenticate for step 2" update_button = requestParameters.get("loginForm:updateButton") if ArrayHelper.isEmpty(update_button): return True find_user_by_uid.setAttribute("oxPasswordExpirationDate", newExpDate) new_password_array = requestParameters.get("loginForm:password") if ArrayHelper.isEmpty(new_password_array) or StringHelper.isEmpty(new_password_array[0]): print "Basic (with password update). Authenticate for step 2. New password is empty" return False new_password = new_password_array[0] find_user_by_uid.setAttribute("userPassword", new_password) print "Basic (with password update). Authenticate for step 2. Attempting to set new user '%s' password" % user_name userService.updateUser(find_user_by_uid) print "Basic (with password update). Authenticate for step 2. Password updated successfully" return True else: return False
def authenticate(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() session_attributes = identity.getSessionId().getSessionAttributes() self.setRequestScopedParameters(identity) if (step == 1): print "UAF. Authenticate for step 1" user_name = credentials.getUsername() authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False uaf_auth_method = "authenticate" # Uncomment this block if you need to allow user second device registration #enrollment_mode = ServerUtil.getFirstValue(requestParameters, "loginForm:registerButton") #if StringHelper.isNotEmpty(enrollment_mode): # uaf_auth_method = "enroll" if uaf_auth_method == "authenticate": user_enrollments = self.findEnrollments(credentials) if len(user_enrollments) == 0: uaf_auth_method = "enroll" print "UAF. Authenticate for step 1. There is no UAF enrollment for user '%s'. Changing uaf_auth_method to '%s'" % (user_name, uaf_auth_method) print "UAF. Authenticate for step 1. uaf_auth_method: '%s'" % uaf_auth_method identity.setWorkingParameter("uaf_auth_method", uaf_auth_method) return True elif (step == 2): print "UAF. Authenticate for step 2" session = CdiUtil.bean(SessionIdService).getSessionId() if session == None: print "UAF. Prepare for step 2. Failed to determine session_id" return False user = authenticationService.getAuthenticatedUser() if (user == None): print "UAF. Authenticate for step 2. Failed to determine user name" return False user_name = user.getUserId() uaf_auth_result = ServerUtil.getFirstValue(requestParameters, "auth_result") if uaf_auth_result != "success": print "UAF. Authenticate for step 2. auth_result is '%s'" % uaf_auth_result return False # Restore state from session uaf_auth_method = session_attributes.get("uaf_auth_method") if not uaf_auth_method in ['enroll', 'authenticate']: print "UAF. Authenticate for step 2. Failed to authenticate user. uaf_auth_method: '%s'" % uaf_auth_method return False # Request STATUS_OBB if True: #TODO: Remove this condition # It's workaround becuase it's not possible to call STATUS_OBB 2 times. First time on browser and second ime on server uaf_user_device_handle = ServerUtil.getFirstValue(requestParameters, "auth_handle") else: uaf_obb_auth_method = session_attributes.get("uaf_obb_auth_method") uaf_obb_server_uri = session_attributes.get("uaf_obb_server_uri") uaf_obb_start_response = session_attributes.get("uaf_obb_start_response") # Prepare STATUS_OBB uaf_obb_start_response_json = json.loads(uaf_obb_start_response) uaf_obb_status_request_dictionary = { "operation": "STATUS_%s" % uaf_obb_auth_method, "userName": user_name, "needDetails": 1, "oobStatusHandle": uaf_obb_start_response_json["oobStatusHandle"], } uaf_obb_status_request = json.dumps(uaf_obb_status_request_dictionary, separators=(',',':')) print "UAF. Authenticate for step 2. Prepared STATUS request: '%s' to send to '%s'" % (uaf_obb_status_request, uaf_obb_server_uri) uaf_status_obb_response = self.executePost(uaf_obb_server_uri, uaf_obb_status_request) if uaf_status_obb_response == None: return False print "UAF. Authenticate for step 2. Get STATUS response: '%s'" % uaf_status_obb_response uaf_status_obb_response_json = json.loads(uaf_status_obb_response) if uaf_status_obb_response_json["statusCode"] != 4000: print "UAF. Authenticate for step 2. UAF operation status is invalid. statusCode: '%s'" % uaf_status_obb_response_json["statusCode"] return False uaf_user_device_handle = uaf_status_obb_response_json["additionalInfo"]["authenticatorsResult"]["handle"] if StringHelper.isEmpty(uaf_user_device_handle): print "UAF. Prepare for step 2. Failed to get UAF handle" return False uaf_user_external_uid = "uaf:%s" % uaf_user_device_handle print "UAF. Authenticate for step 2. UAF handle: '%s'" % uaf_user_external_uid if uaf_auth_method == "authenticate": # Validate if user used device with same keYHandle user_enrollments = self.findEnrollments(credentials) if len(user_enrollments) == 0: uaf_auth_method = "enroll" print "UAF. Authenticate for step 2. There is no UAF enrollment for user '%s'." % user_name return False for user_enrollment in user_enrollments: if StringHelper.equalsIgnoreCase(user_enrollment, uaf_user_device_handle): print "UAF. Authenticate for step 2. There is UAF enrollment for user '%s'. User authenticated successfully" % user_name return True else: userService = CdiUtil.bean(UserService) # Double check just to make sure. We did checking in previous step # Check if there is user which has uaf_user_external_uid # Avoid mapping user cert to more than one IDP account find_user_by_external_uid = userService.getUserByAttribute("oxExternalUid", uaf_user_external_uid) if find_user_by_external_uid == None: # Add uaf_user_external_uid to user's external GUID list find_user_by_external_uid = userService.addUserAttribute(user_name, "oxExternalUid", uaf_user_external_uid) if find_user_by_external_uid == None: print "UAF. Authenticate for step 2. Failed to update current user" return False return True return False else: return False
def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) if (step == 1): print "BCrypt Auth. Authenticate for step 1" identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): userService = CdiUtil.bean(UserService) user = userService.getUser(user_name) hashed_stored_pass = user.getAttribute("userPassword") password_schema = '' # Determine password schema # Example for BCrypt: {BCRYPT}$2b$08$71gBXNKJ/iUBXqLjEdEXFesoUYQm5vrpKefi8YhV7ITGfAd9VNFaG for char in hashed_stored_pass: if char == '{': continue if char == '}': break password_schema = password_schema + char print("Password Schema is: " + password_schema) # OpenDJ's SSHA(512) if 'SSHA' in password_schema: # Returns True if authenticated on the backend logged_in = authenticationService.authenticate(user_name, user_password) # Pattern match BCRYPT and rewrite to SSHA elif 'BCRYPT' in password_schema: # Pull salt from the stored hashed password salt = hashed_stored_pass[8:] salt = salt.split("$")[3].strip() salt = salt[0:22] salt = '$2a$08$' + salt # Create BCrypt hash of challenge cleartext password using the gathered salt challenge = BCrypt.hashpw(user_password,salt) # Strip unnecessary revision($2a$) and rounds(08$) from both hashed passwords for comparison. challenge = challenge.split("$")[3].strip() stored = hashed_stored_pass.split("$")[3].strip() print("Challenge Salt+Hash: " + challenge) print("Stored Salt+Hash: " + stored) # Compare the hashses and update hash if there is a match. if challenge in stored: # Users hashed challenge password matches the stored hashed password in the backend # Therefore we update the users password to the backend's password schema by passing it to OpenDJ print("Updating hash..") user.setAttribute("userPassword",user_password) user = userService.updateUser(user) print("Logging in..") # Returns True logged_in = authenticationService.authenticate(user_name) # Catch unknown schema types and output to oxauth_script.log # This script can be expanded to include other password schemas. else: print("Unrecognized algorithm: " + password_schema) # If there is no match, logged_in will still be False and authentication will fail. if (not logged_in): return False logged_in = authenticationService.authenticate(user_name) return logged_in else: return False
def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis self.mobile_number = None self.identity = CdiUtil.bean(Identity)
def bindWWPass(self, requestParameters, userService, authenticationService, identity, ticket): puid = identity.getWorkingParameter("puid") email = requestParameters.get('email')[0] if 'email' in requestParameters else None if not puid: identity.setWorkingParameter("errors", "WWPass login failed") return False if ticket: puid_new = self.getPuid(ticket) # Always use the latest PUID when retrying step 2 identity.setWorkingParameter("puid", puid_new) if puid == puid_new: # Registering via external web service if not self.registration_url: return False if self.tryFirstLogin(puid, userService, authenticationService): identity.setWorkingParameter("puid", None) return True else: if not self.allow_passkey_bind: return False # Binding with existing PassKey user = userService.getUserByAttribute("oxExternalUid", "wwpass:%s"%puid_new) if user: if authenticationService.authenticate(user.getUserId()): userService.addUserAttribute(user.getUserId(), "oxExternalUid", "wwpass:%s"%puid) identity.setWorkingParameter("puid", None) return True identity.setWorkingParameter("errors", "Invalid user") return False elif email: # Binding via email if not self.allow_email_bind: return False email = requestParameters.get('email')[0] if 'email' in requestParameters else None identity.setWorkingParameter("email", email) user = userService.getUserByAttribute('mail', email) if not user: print("User with email '%s' not found." % email) return True nonce = self.generateNonce(33) mailService = CdiUtil.bean(MailService) identity.setWorkingParameter("email_nonce", nonce) identity.setWorkingParameter("email_nonce_exp", str(time() + self.EMAIL_NONCE_EXPIRATION)) subject = "Bind your WWPass Key" body = """ To bind your WWPass Key to your account, copy and paste the following code into "Email code" field in the login form: %s If you haven't requested this operation, you can safely disregard this email. """ mailService.sendMail(email, subject, body % nonce) return True else: # Binding via username/password if not self.allow_password_bind: return False puid = identity.getWorkingParameter("puid") if not puid: return False credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): try: logged_in = authenticationService.authenticate(user_name, user_password) except Exception as e: print(e) if not logged_in: identity.setWorkingParameter("errors", "Invalid username or password") return False user = authenticationService.getAuthenticatedUser() if not user: identity.setWorkingParameter("errors", "Invalid user") return False userService.addUserAttribute(user_name, "oxExternalUid", "wwpass:%s"%puid) identity.setWorkingParameter("puid", None) return True return False
def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() self.setRequestScopedParameters(identity) if step == 1: print "OTP. Authenticate for step 1" authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False otp_auth_method = "authenticate" # Uncomment this block if you need to allow user second OTP registration #enrollment_mode = ServerUtil.getFirstValue(requestParameters, "loginForm:registerButton") #if StringHelper.isNotEmpty(enrollment_mode): # otp_auth_method = "enroll" if otp_auth_method == "authenticate": user_enrollments = self.findEnrollments(authenticated_user.getUserId()) if len(user_enrollments) == 0: otp_auth_method = "enroll" print "OTP. Authenticate for step 1. There is no OTP enrollment for user '%s'. Changing otp_auth_method to '%s'" % (authenticated_user.getUserId(), otp_auth_method) if otp_auth_method == "enroll": print "OTP. Authenticate for step 1. Setting count steps: '%s'" % 3 identity.setWorkingParameter("otp_count_login_steps", 3) print "OTP. Authenticate for step 1. otp_auth_method: '%s'" % otp_auth_method identity.setWorkingParameter("otp_auth_method", otp_auth_method) return True elif step == 2: print "OTP. Authenticate for step 2" authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if user == None: print "OTP. Authenticate for step 2. Failed to determine user name" return False session_id_validation = self.validateSessionId(identity) if not session_id_validation: return False # Restore state from session identity.setWorkingParameter("retry_current_step", False) otp_auth_method = identity.getWorkingParameter("otp_auth_method") if otp_auth_method == 'enroll': auth_result = ServerUtil.getFirstValue(requestParameters, "auth_result") if not StringHelper.isEmpty(auth_result): # defect fix #1225 - Retry the step, show QR code again if auth_result == 'timeout': print "OTP. QR-code timeout. Authenticate for step %s. Reinitializing current step" % step identity.setWorkingParameter("retry_current_step", True) return True print "OTP. Authenticate for step 2. User not enrolled OTP" return False print "OTP. Authenticate for step 2. Skipping this step during enrollment" return True otp_auth_result = self.processOtpAuthentication(requestParameters, user.getUserId(), identity, otp_auth_method) print "OTP. Authenticate for step 2. OTP authentication result: '%s'" % otp_auth_result return otp_auth_result elif step == 3: print "OTP. Authenticate for step 3" authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if user == None: print "OTP. Authenticate for step 2. Failed to determine user name" return False session_id_validation = self.validateSessionId(identity) if not session_id_validation: return False # Restore state from session otp_auth_method = identity.getWorkingParameter("otp_auth_method") if otp_auth_method != 'enroll': return False otp_auth_result = self.processOtpAuthentication(requestParameters, user.getUserId(), identity, otp_auth_method) print "OTP. Authenticate for step 3. OTP authentication result: '%s'" % otp_auth_result return otp_auth_result else: return False
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 "PhoneFactor. Authenticate for step 1" 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 "PhoneFactor. Authenticate for step 2" passed_step1 = self.isPassedDefaultAuthentication if (not passed_step1): return False pf_phone_number_attr = configurationAttributes.get("pf_phone_number_attr").getValue2() # Get user entry from credentials authenticationService = CdiUtil.bean(AuthenticationService) credentials_user = authenticationService.getAuthenticatedUser() userService = CdiUtil.bean(UserService) phone_number_with_country_code_attr = userService.getCustomAttribute(credentials_user, pf_phone_number_attr) if (phone_number_with_country_code_attr == None): print "PhoneFactor. Authenticate for step 2. There is no phone number: ", user_name return False phone_number_with_country_code = phone_number_with_country_code_attr.getValue() if (phone_number_with_country_code == None): print "PhoneFactor. Authenticate for step 2. There is no phone number: ", user_name return False pf_country_delimiter = configurationAttributes.get("pf_country_delimiter").getValue2() phone_number_with_country_code_array = string.split(phone_number_with_country_code, pf_country_delimiter, 1) phone_number_with_country_code_array_len = len(phone_number_with_country_code_array) if (phone_number_with_country_code_array_len == 1): country_code = "" phone_number = phone_number_with_country_code_array[0] else: country_code = phone_number_with_country_code_array[0] phone_number = phone_number_with_country_code_array[1] print "PhoneFactor. Authenticate for step 2. user_name: ", user_name, ", country_code: ", country_code, ", phone_number: ", phone_number pf_auth_result = None try: pf_auth_result = self.pf.authenticate(user_name, country_code, phone_number, None, None, None) except SecurityException, err: print "PhoneFactor. Authenticate for step 2. BAD AUTH -- Security issue: ", err except TimeoutException, err: print "PhoneFactor. Authenticate for step 2. BAD AUTH -- Server timeout: ", err
def attemptAuthentication(self, identity, user_profile, user_profile_json): print "Entered attemptAuthentication..." uidKey = "uid" if not self.checkRequiredAttributes(user_profile, [uidKey, self.providerKey]): return False provider = user_profile[self.providerKey] print "user_profile[self.providerKey] = %s" % str(user_profile[self.providerKey]) if not provider in self.registeredProviders: print "Entered if note provider in self.registeredProviers:" print "Passport. attemptAuthentication. Identity Provider %s not recognized" % provider return False print "attemptAuthentication. user_profile = %s" % user_profile print "user_profile[uidKey] = %s" % user_profile[uidKey] uid = user_profile[uidKey][0] print "attemptAuthentication - uid = %s" % uid externalUid = "passport-%s:%s:%s" % ("saml", provider, uid) userService = CdiUtil.bean(UserService) userByUid = self.getUserByExternalUid(uid, provider, userService) email = None if "mail" in user_profile: email = user_profile["mail"] if len(email) == 0: email = None else: email = email[0] user_profile["mail"] = [ email ] if email == None and self.registeredProviders[provider]["requestForEmail"]: print "Passport. attemptAuthentication. Email was not received" if userByUid != None: # This avoids asking for the email over every login attempt email = userByUid.getAttribute("mail") if email != None: print "Passport. attemptAuthentication. Filling missing email value with %s" % email user_profile["mail"] = [ email ] if email == None: # Store user profile in session and abort this routine identity.setWorkingParameter("passport_user_profile", user_profile_json) return True userByMail = None if email == None else userService.getUserByAttribute("mail", email) # Determine if we should add entry, update existing, or deny access doUpdate = False doAdd = False if userByUid != None: print "User with externalUid '%s' already exists" % externalUid if userByMail == None: doUpdate = True else: if userByMail.getUserId() == userByUid.getUserId(): doUpdate = True else: print "Users with externalUid '%s' and mail '%s' are different. Access will be denied. Impersonation attempt?" % (externalUid, email) self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email value corresponds to an already existing provisioned account") else: if userByMail == None: doAdd = True elif self.registeredProviders[provider]["emailLinkingSafe"]: tmpList = userByMail.getAttributeValues("oxExternalUid") tmpList = ArrayList() if tmpList == None else ArrayList(tmpList) tmpList.add(externalUid) userByMail.setAttribute("oxExternalUid", tmpList, True) userByUid = userByMail print "External user supplying mail %s will be linked to existing account '%s'" % (email, userByMail.getUserId()) doUpdate = True else: print "An attempt to supply an email of an existing user was made. Turn on 'emailLinkingSafe' if you want to enable linking" self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email value corresponds to an already existing account. If you already have a username and password use those instead of an external authentication site to get access.") username = None try: if doUpdate: username = userByUid.getUserId() print "Passport. attemptAuthentication. Updating user %s" % username self.updateUser(userByUid, user_profile, userService) elif doAdd: print "Passport. attemptAuthentication. Creating user %s" % externalUid newUser = self.addUser(externalUid, user_profile, userService) username = newUser.getUserId() except: print "Exception: ", sys.exc_info()[1] print "Passport. attemptAuthentication. Authentication failed" return False if username == None: print "Passport. attemptAuthentication. Authentication attempt was rejected" return False else: logged_in = CdiUtil.bean(AuthenticationService).authenticate(username) print "Passport. attemptAuthentication. Authentication for %s returned %s" % (username, logged_in) return logged_in
def setMessageError(self, severity, msg): facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() facesMessages.clear() facesMessages.add(severity, msg)
def prepareForStep(self, configurationAttributes, requestParameters, step): extensionResult = self.extensionPrepareForStep(configurationAttributes, requestParameters, step) if extensionResult != None: return extensionResult print "Passport. prepareForStep called %s" % str(step) identity = CdiUtil.bean(Identity) if step == 1: #re-read the strategies config (for instance to know which strategies have enabled the email account linking) self.parseProviderConfigs() identity.setWorkingParameter("externalProviders", json.dumps(self.registeredProviders)) providerParam = self.customAuthzParameter url = None sessionAttributes = identity.getSessionId().getSessionAttributes() self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get("skipPassportProfileUpdate"), "true") #this param could have been set previously in authenticate step if current step is being retried provider = identity.getWorkingParameter("selectedProvider") print "prepareForStep %s - provider = %s" % (str(step), str(provider)) # if there is a selectedProvider if provider != None: # get the redirect URL to use at facesService.redirectToExternalURL() that sends /passport/auth/<provider>/<token> url = self.getPassportRedirectUrl(provider) print "prepareForStep %s - url = %s" % (str(step), url) # sets selectedProvider back to None identity.setWorkingParameter("selectedProvider", None) # if there is customAuthzParameter elif providerParam != None: # get it from sessionAtributes paramValue = sessionAttributes.get(providerParam) #if exists if paramValue != None: print "Passport. prepareForStep. Found value in custom param of authorization request: %s" % paramValue provider = self.getProviderFromJson(paramValue) if provider == None: print "Passport. prepareForStep. A provider value could not be extracted from custom authorization request parameter" elif not provider in self.registeredProviders: print "Passport. prepareForStep. Provider '%s' not part of known configured IDPs/OPs" % provider else: url = self.getPassportRedirectUrl(provider) # if no provider selected yet... if url == None: print "Passport. prepareForStep. A page to manually select an identity provider will be shown" # else already got the /passport/auth/<provider>/<token> url... else: facesService = CdiUtil.bean(FacesService) # redirects to Passport getRedirectURL - sends browser to IDP. print "Passport. Redirecting to external url: %s" + url facesService.redirectToExternalURL(url) return True
def getCountAuthenticationSteps(self, configurationAttributes): print "Passport. getCountAuthenticationSteps called" identity = CdiUtil.bean(Identity) if identity.getWorkingParameter("passport_user_profile") != None: return 2 return 1
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" 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 authenticate(self, configurationAttributes, requestParameters, step): print "Wikid. Authentication. Checking client" if (not self.wc.isConnected()): print "Wikid. Authentication. Wikid client state is invalid" return False authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() is_wikid_registration = False sessionAttributes = identity.getSessionId().getSessionAttributes() if (sessionAttributes != None) and sessionAttributes.containsKey("wikid_registration"): is_wikid_registration = java.lang.Boolean.valueOf(sessionAttributes.get("wikid_registration")) wikid_server_code = configurationAttributes.get("wikid_server_code").getValue2() user_name = credentials.getUsername() if (step == 1): print "Wikid. Authenticate for step 1" 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 print "Wikid. Authenticate for step 1. Attempting to find wikid_user: "******"Wikid. Authenticate for step 1. There is no associated devices for user: "******"Wikid. Authenticate for step 1. Setting count steps to 3" identity.setWorkingParameter("wikid_count_login_steps", 3) identity.setWorkingParameter("wikid_registration", True) else: identity.setWorkingParameter("wikid_count_login_steps", 2) return True elif (is_wikid_registration): print "Wikid. Authenticate for step wikid_register_device" userService = CdiUtil.bean(UserService) wikid_regcode_array = requestParameters.get("regcode") if ArrayHelper.isEmpty(wikid_regcode_array): print "Wikid. Authenticate for step wikid_register_device. Regcode is empty" return False wikid_regcode = wikid_regcode_array[0] print "Wikid. Authenticate for step wikid_register_device. User: "******", regcode: " + wikid_regcode register_result = self.wc.registerUsername(user_name, wikid_regcode, wikid_server_code) is_valid = register_result == 0 if is_valid: print "Wikid. Authenticate for step wikid_register_device. User: "******" token registered successfully" # Add wikid_regcode to user UIDs find_user_by_uid = userService.addUserAttribute(user_name, "oxExternalUid", "wikid:" + wikid_regcode) if (find_user_by_uid == None): print "Wikid. Authenticate for step wikid_register_device. Failed to update user: "******"wikid_registration", False) else: print "Wikid. Authenticate for step wikid_register_device. Failed to register user: "******" token:" + wikid_regcode + ". Registration result:", register_result return is_valid elif (not is_wikid_registration): print "Wikid. Authenticate for step wikid_check_passcode" wikid_passcode_array = requestParameters.get("passcode") if ArrayHelper.isEmpty(wikid_passcode_array): print "Wikid. Authenticate for step wikid_check_passcode. Passcode is empty" return False wikid_passcode = wikid_passcode_array[0] print "Wikid. Authenticate for step wikid_check_passcode. wikid_user: "******"Wikid. Authenticate for step wikid_check_passcode. wikid_user: "******" authenticated successfully" else: print "Wikid. Authenticate for step wikid_check_passcode. Failed to authenticate. wikid_user: " + user_name return is_valid else: return False
def hasEnrollments(self, configurationAttributes, user): return CdiUtil.bean(UserService).countFido2RegisteredDevices(user.getUserId()) > 0
def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis self.identity = CdiUtil.bean(Identity)
def authenticate(self, configurationAttributes, requestParameters, step): extensionResult = self.extensionAuthenticate(configurationAttributes, requestParameters, step) if extensionResult != None: return extensionResult print "Passport. authenticate for step %s called" % str(step) identity = CdiUtil.bean(Identity) # Loading self.registeredProviders in case passport destroyed if not hasattr(self,'registeredProviders'): print "Passport. Fetching registered providers." self.parseProviderConfigs() if step == 1: jwt_param = None if self.isInboundFlow(identity): # if is idp-initiated inbound flow print "Passport. authenticate for step 1. Detected idp-initiated inbound Saml flow" # get request from session attributes jwt_param = identity.getSessionId().getSessionAttributes().get(AuthorizeRequestParam.STATE) print "jwt_param = %s" % jwt_param # now jwt_param != None if jwt_param == None: # gets jwt parameter "user" sent after authentication by passport (if exists) jwt_param = ServerUtil.getFirstValue(requestParameters, "user") if jwt_param != None: # and now that the jwt_param user exists... print "Passport. authenticate for step 1. JWT user profile token found" if self.isInboundFlow(identity): jwt_param = base64.urlsafe_b64decode(str(jwt_param+'==')) # Parse JWT and validate jwt = Jwt.parse(jwt_param) if not self.validSignature(jwt): return False if self.jwtHasExpired(jwt): return False # Gets user profile as string and json using the information on JWT (user_profile, jsonp) = self.getUserProfile(jwt) if user_profile == None: return False sessionAttributes = identity.getSessionId().getSessionAttributes() self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get("skipPassportProfileUpdate"), "true") return self.attemptAuthentication(identity, user_profile, jsonp) #See passportlogin.xhtml provider = ServerUtil.getFirstValue(requestParameters, "loginForm:provider") if StringHelper.isEmpty(provider): #it's username + passw auth print "Passport. authenticate for step 1. Basic authentication detected" logged_in = False credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): authenticationService = CdiUtil.bean(AuthenticationService) logged_in = authenticationService.authenticate(user_name, user_password) print "Passport. authenticate for step 1. Basic authentication returned: %s" % logged_in return logged_in elif provider in self.registeredProviders: # user selected provider # it's a recognized external IDP identity.setWorkingParameter("selectedProvider", provider) print "Passport. authenticate for step 1. Retrying step 1" #see prepareForStep (step = 1) return True if step == 2: mail = ServerUtil.getFirstValue(requestParameters, "loginForm:email") jsonp = identity.getWorkingParameter("passport_user_profile") if mail == None: self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email was missing in user profile") elif jsonp != None: # Completion of profile takes place user_profile = json.loads(jsonp) user_profile["mail"] = [ mail ] return self.attemptAuthentication(identity, user_profile, jsonp) print "Passport. authenticate for step 2. Failed: expected mail value in HTTP request and json profile in session" return False
def authenticate(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) httpService = CdiUtil.bean(HttpService) server_flag = configurationAttributes.get("oneid_server_flag").getValue2() callback_attrs = configurationAttributes.get("oneid_callback_attrs").getValue2() creds_file = configurationAttributes.get("oneid_creds_file").getValue2() # Create OneID authn = OneID(server_flag) # Set path to credentials file authn.creds_file = creds_file if (step == 1): print "OneId. Authenticate for step 1" # Find OneID request json_data_array = requestParameters.get("json_data") if ArrayHelper.isEmpty(json_data_array): print "OneId. Authenticate for step 1. json_data is empty" return False request = json_data_array[0] print "OneId. Authenticate for step 1. request: " + request if (StringHelper.isEmptyString(request)): return False authn.set_credentials() # Validate request http_client = httpService.getHttpsClientDefaulTrustStore() auth_data = httpService.encodeBase64(authn.api_id + ":" + authn.api_key) http_response = httpService.executePost(http_client, authn.helper_server + "/validate", auth_data, request, ContentType.APPLICATION_JSON) validation_content = httpService.convertEntityToString(httpService.getResponseContent(http_response)) print "OneId. Authenticate for step 1. validation_content: " + validation_content if (StringHelper.isEmptyString(validation_content)): return False validation_resp = json.loads(validation_content) print "OneId. Authenticate for step 1. validation_resp: " + str(validation_resp) if (not authn.success(validation_resp)): return False response = json.loads(request) for x in validation_resp: response[x] = validation_resp[x] oneid_user_uid = response['uid'] print "OneId. Authenticate for step 1. oneid_user_uid: " + oneid_user_uid # Check if the is user with specified oneid_user_uid find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "oneid:" + oneid_user_uid) if (find_user_by_uid == None): print "OneId. Authenticate for step 1. Failed to find user" print "OneId. Authenticate for step 1. Setting count steps to 2" identity.setWorkingParameter("oneid_count_login_steps", 2) identity.setWorkingParameter("oneid_user_uid", oneid_user_uid) return True found_user_name = find_user_by_uid.getUserId() print "OneId. Authenticate for step 1. found_user_name: " + found_user_name identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() credentials.setUsername(found_user_name) credentials.setUser(find_user_by_uid) print "OneId. Authenticate for step 1. Setting count steps to 1" identity.setWorkingParameter("oneid_count_login_steps", 1) return True elif (step == 2): print "OneId. Authenticate for step 2" sessionAttributes = identity.getSessionId().getSessionAttributes() if (sessionAttributes == None) or not sessionAttributes.containsKey("oneid_user_uid"): print "OneId. Authenticate for step 2. oneid_user_uid is empty" return False oneid_user_uid = sessionAttributes.get("oneid_user_uid") passed_step1 = StringHelper.isNotEmptyString(oneid_user_uid) if (not passed_step1): return False identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() passed_step1 = StringHelper.isNotEmptyString(user_name) if (not passed_step1): return False identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): logged_in = authenticationService.authenticate(user_name, user_password) if (not logged_in): return False # Check if there is user which has oneid_user_uid # Avoid mapping OneID account to more than one IDP account find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "oneid:" + oneid_user_uid) if (find_user_by_uid == None): # Add oneid_user_uid to user one id UIDs find_user_by_uid = userService.addUserAttribute(user_name, "oxExternalUid", "oneid:" + oneid_user_uid) if (find_user_by_uid == None): print "OneId. Authenticate for step 2. Failed to update current user" return False return True else: found_user_name = find_user_by_uid.getUserId() print "OneId. Authenticate for step 2. found_user_name: " + found_user_name if StringHelper.equals(user_name, found_user_name): return True return False else: return False
def authenticate(self, configurationAttributes, requestParameters, step): userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) iw_api_uri = configurationAttributes.get("iw_api_uri").getValue2() iw_service_id = configurationAttributes.get("iw_service_id").getValue2() iw_helium_enabled = Boolean(configurationAttributes.get("iw_helium_enabled").getValue2()).booleanValue() if (iw_helium_enabled): identity.setWorkingParameter("iw_count_login_steps", 1) credentials = identity.getCredentials() user_name = credentials.getUsername() if (step == 1): print "InWebo. Authenticate for step 1" print "InWebo. Authenticate for step 1. iw_helium_enabled:", iw_helium_enabled user_password = credentials.getPassword() if (iw_helium_enabled): login_array = requestParameters.get("login") if ArrayHelper.isEmpty(login_array): print "InWebo. Authenticate for step 1. login is empty" return False user_name = login_array[0] password_array = requestParameters.get("password") if ArrayHelper.isEmpty(password_array): print "InWebo. Authenticate for step 1. password is empty" return False user_password = password_array[0] response_validation = self.validateInweboToken(iw_api_uri, iw_service_id, user_name, user_password) if (not response_validation): return False logged_in = False if (StringHelper.isNotEmptyString(user_name)): userService = CdiUtil.bean(UserService) logged_in = authenticationService.authenticate(user_name) return logged_in else: 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) return logged_in return True elif (step == 2): print "InWebo. Authenticate for step 2" passed_step1 = self.isPassedDefaultAuthentication if (not passed_step1): return False iw_token_array = requestParameters.get("iw_token") if ArrayHelper.isEmpty(iw_token_array): print "InWebo. Authenticate for step 2. iw_token is empty" return False iw_token = iw_token_array[0] response_validation = self.validateInweboToken(iw_api_uri, iw_service_id, user_name, iw_token) return response_validation else: return False
def processOtpAuthentication(self, requestParameters, user_name, identity, otp_auth_method): facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() userService = CdiUtil.bean(UserService) otpCode = ServerUtil.getFirstValue(requestParameters, "loginForm:otpCode") if StringHelper.isEmpty(otpCode): facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to authenticate. OTP code is empty") print "OTP. Process OTP authentication. otpCode is empty" return False if otp_auth_method == "enroll": # Get key from session otp_secret_key_encoded = identity.getWorkingParameter("otp_secret_key") if otp_secret_key_encoded == None: print "OTP. Process OTP authentication. OTP secret key is invalid" return False otp_secret_key = self.fromBase64Url(otp_secret_key_encoded) if self.otpType == "hotp": validation_result = self.validateHotpKey(otp_secret_key, 1, otpCode) if (validation_result != None) and validation_result["result"]: print "OTP. Process HOTP authentication during enrollment. otpCode is valid" # Store HOTP Secret Key and moving factor in user entry otp_user_external_uid = "hotp:%s;%s" % ( otp_secret_key_encoded, validation_result["movingFactor"] ) # Add otp_user_external_uid to user's external GUID list find_user_by_external_uid = userService.addUserAttribute(user_name, "oxExternalUid", otp_user_external_uid, True) if find_user_by_external_uid != None: return True print "OTP. Process HOTP authentication during enrollment. Failed to update user entry" elif self.otpType == "totp": validation_result = self.validateTotpKey(otp_secret_key, otpCode,user_name) if (validation_result != None) and validation_result["result"]: print "OTP. Process TOTP authentication during enrollment. otpCode is valid" # Store TOTP Secret Key and moving factor in user entry otp_user_external_uid = "totp:%s" % otp_secret_key_encoded # Add otp_user_external_uid to user's external GUID list find_user_by_external_uid = userService.addUserAttribute(user_name, "oxExternalUid", otp_user_external_uid, True) if find_user_by_external_uid != None: return True print "OTP. Process TOTP authentication during enrollment. Failed to update user entry" elif otp_auth_method == "authenticate": user_enrollments = self.findEnrollments(user_name) if len(user_enrollments) == 0: print "OTP. Process OTP authentication. There is no OTP enrollment for user '%s'" % user_name facesMessages.add(FacesMessage.SEVERITY_ERROR, "There is no valid OTP user enrollments") return False if self.otpType == "hotp": for user_enrollment in user_enrollments: user_enrollment_data = user_enrollment.split(";") otp_secret_key_encoded = user_enrollment_data[0] # Get current moving factor from user entry moving_factor = StringHelper.toInteger(user_enrollment_data[1]) otp_secret_key = self.fromBase64Url(otp_secret_key_encoded) # Validate TOTP validation_result = self.validateHotpKey(otp_secret_key, moving_factor, otpCode) if (validation_result != None) and validation_result["result"]: print "OTP. Process HOTP authentication during authentication. otpCode is valid" otp_user_external_uid = "hotp:%s;%s" % ( otp_secret_key_encoded, moving_factor ) new_otp_user_external_uid = "hotp:%s;%s" % ( otp_secret_key_encoded, validation_result["movingFactor"] ) # Update moving factor in user entry find_user_by_external_uid = userService.replaceUserAttribute(user_name, "oxExternalUid", otp_user_external_uid, new_otp_user_external_uid, True) if find_user_by_external_uid != None: return True print "OTP. Process HOTP authentication during authentication. Failed to update user entry" elif self.otpType == "totp": for user_enrollment in user_enrollments: otp_secret_key = self.fromBase64Url(user_enrollment) # Validate TOTP validation_result = self.validateTotpKey(otp_secret_key, otpCode, user_name) if (validation_result != None) and validation_result["result"]: print "OTP. Process TOTP authentication during authentication. otpCode is valid" return True facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to authenticate. OTP code is invalid") print "OTP. Process OTP authentication. OTP code is invalid" return False
def authenticate(self, configurationAttributes, requestParameters, step): duo_host = configurationAttributes.get("duo_host").getValue2() authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) if (step == 1): print "Duo. Authenticate for step 1" # Check if user authenticated already in another custom script user = authenticationService.getAuthenticatedUser() if user == None: credentials = identity.getCredentials() user_name = credentials.getUsername() 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 user = authenticationService.getAuthenticatedUser() if (self.use_duo_group): print "Duo. Authenticate for step 1. Checking if user belong to Duo group" is_member_duo_group = self.isUserMemberOfGroup(user, self.audit_attribute, self.duo_group) if (is_member_duo_group): print "Duo. Authenticate for step 1. User '" + user.getUserId() + "' member of Duo group" duo_count_login_steps = 2 else: self.processAuditGroup(user) duo_count_login_steps = 1 identity.setWorkingParameter("duo_count_login_steps", duo_count_login_steps) return True elif (step == 2): print "Duo. Authenticate for step 2" user = authenticationService.getAuthenticatedUser() if user == None: print "Duo. Authenticate for step 2. Failed to determine user name" return False user_name = user.getUserId() sig_response_array = requestParameters.get("sig_response") if ArrayHelper.isEmpty(sig_response_array): print "Duo. Authenticate for step 2. sig_response is empty" return False duo_sig_response = sig_response_array[0] print "Duo. Authenticate for step 2. duo_sig_response: " + duo_sig_response authenticated_username = duo_web.verify_response(self.ikey, self.skey, self.akey, duo_sig_response) print "Duo. Authenticate for step 2. authenticated_username: "******", expected user_name: " + user_name if (not StringHelper.equals(user_name, authenticated_username)): return False self.processAuditGroup(user) return True else: return False
class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis self.mobile_number = None self.identity = CdiUtil.bean(Identity) def init(self, customScript, configurationAttributes): print "==============================================" print "===TWILIO SMS INITIALIZATION==================" print "==============================================" self.ACCOUNT_SID = None self.AUTH_TOKEN = None self.FROM_NUMBER = None # Get Custom Properties try: self.ACCOUNT_SID = configurationAttributes.get("twilio_sid").getValue2() except: print 'TwilioSMS, Missing required configuration attribute "twilio_sid"' try: self.AUTH_TOKEN = configurationAttributes.get("twilio_token").getValue2() except: print'TwilioSMS, Missing required configuration attribute "twilio_token"' try: self.FROM_NUMBER = configurationAttributes.get("from_number").getValue2() except: print'TwilioSMS, Missing required configuration attribute "from_number"' if None in (self.ACCOUNT_SID, self.AUTH_TOKEN, self.FROM_NUMBER): print "twilio_sid, twilio_token, from_number is empty ... returning False" return False print "===TWILIO SMS INITIALIZATION DONE PROPERLY=====" return True def destroy(self, configurationAttributes): print "Twilio SMS. Destroy" print "Twilio SMS. Destroyed successfully" return True def getApiVersion(self): return 11 def getAuthenticationMethodClaims(self, requestParameters): return None def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): print "==============================================" print "====TWILIO SMS AUTHENCATION===================" print "==============================================" userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) sessionIdService = CdiUtil.bean(SessionIdService) facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() session_attributes = self.identity.getSessionId().getSessionAttributes() form_passcode = ServerUtil.getFirstValue(requestParameters, "passcode") form_name = ServerUtil.getFirstValue(requestParameters, "TwilioSmsloginForm") print "TwilioSMS. form_response_passcode: %s" % str(form_passcode) if step == 1: print "==============================================" print "=TWILIO SMS STEP 1 | Password Authentication==" print "==============================================" credentials = self.identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): logged_in = authenticationService.authenticate(user_name, user_password) if not logged_in: return False # Get the Person's number and generate a code foundUser = None try: foundUser = authenticationService.getAuthenticatedUser() except: print 'TwilioSMS, Error retrieving user %s from LDAP' % (user_name) return False try: isVerified = foundUser.getAttribute("phoneNumberVerified") if isVerified: self.mobile_number = foundUser.getAttribute("employeeNumber") if self.mobile_number == None: self.mobile_number = foundUser.getAttribute("mobile") if self.mobile_number == None: self.mobile_number = foundUser.getAttribute("telephoneNumber") if self.mobile_number == None: print "TwilioSMS, Error finding mobile number for user '%s'" % user_name except: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to determine mobile phone number") print 'TwilioSMS, Error finding mobile number for "%s". Exception: %s` % (user_name, sys.exc_info()[1])`' return False # Generate Random six digit code and store it in array code = random.randint(100000, 999999) # Get code and save it in LDAP temporarily with special session entry self.identity.setWorkingParameter("code", code) sessionId = sessionIdService.getSessionId() # fetch from persistence sessionId.getSessionAttributes().put("code", code) try: Twilio.init(self.ACCOUNT_SID, self.AUTH_TOKEN); message = Message.creator(PhoneNumber(self.mobile_number), PhoneNumber(self.FROM_NUMBER), str(code)).create(); print "++++++++++++++++++++++++++++++++++++++++++++++" print 'TwilioSMs, Message Sid: %s' % (message.getSid()) print 'TwilioSMs, User phone: %s' % (self.mobile_number) print "++++++++++++++++++++++++++++++++++++++++++++++" sessionId.getSessionAttributes().put("mobile_number", self.mobile_number) sessionId.getSessionAttributes().put("mobile", self.mobile_number) sessionIdService.updateSessionId(sessionId) self.identity.setWorkingParameter("mobile_number", self.mobile_number) self.identity.getSessionId().getSessionAttributes().put("mobile_number",self.mobile_number) self.identity.setWorkingParameter("mobile", self.mobile_number) self.identity.getSessionId().getSessionAttributes().put("mobile",self.mobile_number) print "++++++++++++++++++++++++++++++++++++++++++++++" print "Number: %s" % (self.identity.getWorkingParameter("mobile_number")) print "Mobile: %s" % (self.identity.getWorkingParameter("mobile")) print "++++++++++++++++++++++++++++++++++++++++++++++" print "========================================" print "===TWILIO SMS FIRST STEP DONE PROPERLY==" print "========================================" return True except Exception, ex: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to send message to mobile phone") print "TwilioSMS. Error sending message to Twilio" print "TwilioSMS. Unexpected error:", ex return False elif step == 2: # Retrieve the session attribute print "==============================================" print "=TWILIO SMS STEP 2 | Password Authentication==" print "==============================================" code = session_attributes.get("code") print '=======> Session code is "%s"' % str(code) sessionIdService = CdiUtil.bean(SessionIdService) sessionId = sessionIdService.getSessionId() # fetch from persistence code = sessionId.getSessionAttributes().get("code") print '=======> Database code is "%s"' % str(code) self.identity.setSessionId(sessionId) print "==============================================" print "TwilioSMS. Code: %s" % str(code) print "==============================================" if code is None: print "TwilioSMS. Failed to find previously sent code" return False if form_passcode is None: print "TwilioSMS. Passcode is empty" return False if len(form_passcode) != 6: print "TwilioSMS. Passcode from response is not 6 digits: %s" % form_passcode return False if form_passcode == code: print "TiwlioSMS, SUCCESS! User entered the same code!" print "========================================" print "===TWILIO SMS SECOND STEP DONE PROPERLY" print "========================================" return True print "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" print "TwilioSMS. FAIL! User entered the wrong code! %s != %s" % (form_passcode, code) print "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" facesMessages.add(FacesMessage.SEVERITY_ERROR, "Incorrect Twilio code, please try again.") print "================================================" print "===TWILIO SMS SECOND STEP FAILED: INCORRECT CODE" print "================================================" return False
def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) if step == 1: print "Basic (lock account). Authenticate for step 1" facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() cacheService = CdiUtil.bean(CacheService) userService = CdiUtil.bean(UserService) logged_in = False if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): try: logged_in = authenticationService.authenticate(user_name, user_password) except AuthenticationException: print "Basic (lock account). Authenticate. Failed to authenticate user '%s'" % user_name if logged_in: self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(0)) else: countInvalidLoginArributeValue = self.getUserAttributeValue(user_name, self.invalidLoginCountAttribute) userSatus = self.getUserAttributeValue(user_name, "gluuStatus") print "Current user '%s' status is '%s'" % ( user_name, userSatus ) countInvalidLogin = StringHelper.toInteger(countInvalidLoginArributeValue, 0) if countInvalidLogin < self.maximumInvalidLoginAttemps: countInvalidLogin = countInvalidLogin + 1 remainingAttempts = self.maximumInvalidLoginAttemps - countInvalidLogin print "Remaining login count attempts '%s' for user '%s'" % ( remainingAttempts, user_name ) self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(countInvalidLogin)) if remainingAttempts > 0 and userSatus == "active": facesMessages.add(FacesMessage.SEVERITY_INFO, StringHelper.toString(remainingAttempts)+" more attempt(s) before account is LOCKED!") if (countInvalidLogin >= self.maximumInvalidLoginAttemps) and ((userSatus == None) or (userSatus == "active")): print "Basic (lock account). Locking '%s' for '%s' seconds" % ( user_name, self.lockExpirationTime) self.lockUser(user_name) return False if (countInvalidLogin >= self.maximumInvalidLoginAttemps) and userSatus == "inactive": print "Basic (lock account). User '%s' is locked. Checking if we can unlock him" % user_name unlock_and_authenticate = False object_from_store = cacheService.get(None, "lock_user_" + user_name) if object_from_store == None: # Object in cache was expired. We need to unlock user print "Basic (lock account). User locking details for user '%s' not exists" % user_name unlock_and_authenticate = True else: # Analyze object from cache user_lock_details = json.loads(object_from_store) user_lock_details_locked = user_lock_details['locked'] user_lock_details_created = user_lock_details['created'] user_lock_details_created_date = LocalDateTime.parse(user_lock_details_created, DateTimeFormatter.ISO_LOCAL_DATE_TIME) user_lock_details_created_diff = Duration.between(user_lock_details_created_date, LocalDateTime.now()).getSeconds() print "Basic (lock account). Get user '%s' locking details. locked: '%s', Created: '%s', Difference in seconds: '%s'" % ( user_name, user_lock_details_locked, user_lock_details_created, user_lock_details_created_diff ) if user_lock_details_locked and user_lock_details_created_diff >= self.lockExpirationTime: print "Basic (lock account). Unlocking user '%s' after lock expiration" % user_name unlock_and_authenticate = True if unlock_and_authenticate: self.unLockUser(user_name) self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(0)) logged_in = authenticationService.authenticate(user_name, user_password) if not logged_in: # Update number of attempts self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(1)) if self.maximumInvalidLoginAttemps == 1: # Lock user if maximum count login attempts is 1 self.lockUser(user_name) return False return logged_in else: return False
def authenticate(self, configurationAttributes, requestParameters, step): print "==============================================" print "====TWILIO SMS AUTHENCATION===================" print "==============================================" userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) sessionIdService = CdiUtil.bean(SessionIdService) facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() session_attributes = self.identity.getSessionId().getSessionAttributes() form_passcode = ServerUtil.getFirstValue(requestParameters, "passcode") form_name = ServerUtil.getFirstValue(requestParameters, "TwilioSmsloginForm") print "TwilioSMS. form_response_passcode: %s" % str(form_passcode) if step == 1: print "==============================================" print "=TWILIO SMS STEP 1 | Password Authentication==" print "==============================================" credentials = self.identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): logged_in = authenticationService.authenticate(user_name, user_password) if not logged_in: return False # Get the Person's number and generate a code foundUser = None try: foundUser = authenticationService.getAuthenticatedUser() except: print 'TwilioSMS, Error retrieving user %s from LDAP' % (user_name) return False try: isVerified = foundUser.getAttribute("phoneNumberVerified") if isVerified: self.mobile_number = foundUser.getAttribute("employeeNumber") if self.mobile_number == None: self.mobile_number = foundUser.getAttribute("mobile") if self.mobile_number == None: self.mobile_number = foundUser.getAttribute("telephoneNumber") if self.mobile_number == None: print "TwilioSMS, Error finding mobile number for user '%s'" % user_name except: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to determine mobile phone number") print 'TwilioSMS, Error finding mobile number for "%s". Exception: %s` % (user_name, sys.exc_info()[1])`' return False # Generate Random six digit code and store it in array code = random.randint(100000, 999999) # Get code and save it in LDAP temporarily with special session entry self.identity.setWorkingParameter("code", code) sessionId = sessionIdService.getSessionId() # fetch from persistence sessionId.getSessionAttributes().put("code", code) try: Twilio.init(self.ACCOUNT_SID, self.AUTH_TOKEN); message = Message.creator(PhoneNumber(self.mobile_number), PhoneNumber(self.FROM_NUMBER), str(code)).create(); print "++++++++++++++++++++++++++++++++++++++++++++++" print 'TwilioSMs, Message Sid: %s' % (message.getSid()) print 'TwilioSMs, User phone: %s' % (self.mobile_number) print "++++++++++++++++++++++++++++++++++++++++++++++" sessionId.getSessionAttributes().put("mobile_number", self.mobile_number) sessionId.getSessionAttributes().put("mobile", self.mobile_number) sessionIdService.updateSessionId(sessionId) self.identity.setWorkingParameter("mobile_number", self.mobile_number) self.identity.getSessionId().getSessionAttributes().put("mobile_number",self.mobile_number) self.identity.setWorkingParameter("mobile", self.mobile_number) self.identity.getSessionId().getSessionAttributes().put("mobile",self.mobile_number) print "++++++++++++++++++++++++++++++++++++++++++++++" print "Number: %s" % (self.identity.getWorkingParameter("mobile_number")) print "Mobile: %s" % (self.identity.getWorkingParameter("mobile")) print "++++++++++++++++++++++++++++++++++++++++++++++" print "========================================" print "===TWILIO SMS FIRST STEP DONE PROPERLY==" print "========================================" return True except Exception, ex: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to send message to mobile phone") print "TwilioSMS. Error sending message to Twilio" print "TwilioSMS. Unexpected error:", ex return False
def authenticate(self, configurationAttributes, requestParameters, step): print "Casa. authenticate for step %s" % str(step) userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) if step == 1: credentials = identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): foundUser = userService.getUserByAttribute(self.uid_attr, user_name) #foundUser = userService.getUser(user_name) if foundUser == None: print "Casa. authenticate for step 1. Unknown username" else: platform_data = self.parsePlatformData(requestParameters) preferred = foundUser.getAttribute("oxPreferredMethod") mfaOff = preferred == None logged_in = False if mfaOff: logged_in = authenticationService.authenticate(user_name, user_password) else: acr = self.getSuitableAcr(foundUser, platform_data, preferred) if acr != None: module = self.authenticators[acr] logged_in = module.authenticate(module.configAttrs, requestParameters, step) if logged_in: foundUser = authenticationService.getAuthenticatedUser() if foundUser == None: print "Casa. authenticate for step 1. Cannot retrieve logged user" else: if mfaOff: identity.setWorkingParameter("skip2FA", True) else: #Determine whether to skip 2FA based on policy defined (global or user custom) skip2FA = self.determineSkip2FA(userService, identity, foundUser, platform_data) identity.setWorkingParameter("skip2FA", skip2FA) identity.setWorkingParameter("ACR", acr) return True else: print "Casa. authenticate for step 1 was not successful" return False else: user = authenticationService.getAuthenticatedUser() if user == None: print "Casa. authenticate for step 2. Cannot retrieve logged user" return False #see casa.xhtml alter = ServerUtil.getFirstValue(requestParameters, "alternativeMethod") if alter != None: #bypass the rest of this step if an alternative method was provided. Current step will be retried (see getNextStep) self.simulateFirstStep(requestParameters, alter) return True session_attributes = identity.getSessionId().getSessionAttributes() acr = session_attributes.get("ACR") #this working parameter is used in casa.xhtml identity.setWorkingParameter("methods", ArrayList(self.getAvailMethodsUser(user, acr))) success = False if acr in self.authenticators: module = self.authenticators[acr] success = module.authenticate(module.configAttrs, requestParameters, step) #Update the list of trusted devices if 2fa passed if success: print "Casa. authenticate. 2FA authentication was successful" tdi = session_attributes.get("trustedDevicesInfo") if tdi == None: print "Casa. authenticate. List of user's trusted devices was not updated" else: user.setAttribute("oxTrustedDevicesInfo", tdi) userService.updateUser(user) else: print "Casa. authenticate. 2FA authentication failed" return success return False
def prepareForStep(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() session_attributes = identity.getSessionId().getSessionAttributes() self.setRequestScopedParameters(identity) if (step == 1): return True elif (step == 2): print "UAF. Prepare for step 2" session = CdiUtil.bean(SessionIdService).getSessionId() if session == None: print "UAF. Prepare for step 2. Failed to determine session_id" return False user = authenticationService.getAuthenticatedUser() if (user == None): print "UAF. Prepare for step 2. Failed to determine user name" return False uaf_auth_method = session_attributes.get("uaf_auth_method") if StringHelper.isEmpty(uaf_auth_method): print "UAF. Prepare for step 2. Failed to determine auth_method" return False print "UAF. Prepare for step 2. uaf_auth_method: '%s'" % uaf_auth_method uaf_obb_auth_method = "OOB_REG" uaf_obb_server_uri = self.uaf_server_uri + "/nnl/v2/reg" if StringHelper.equalsIgnoreCase(uaf_auth_method, "authenticate"): uaf_obb_auth_method = "OOB_AUTH" uaf_obb_server_uri = self.uaf_server_uri + "/nnl/v2/auth" # Prepare START_OBB uaf_obb_start_request_dictionary = { "operation": "START_%s" % uaf_obb_auth_method, "userName": user.getUserId(), "policyName": "default", "oobMode": { "qr": "true", "rawData": "false", "push": "false" } } uaf_obb_start_request = json.dumps(uaf_obb_start_request_dictionary, separators=(',',':')) print "UAF. Prepare for step 2. Prepared START request: '%s' to send to '%s'" % (uaf_obb_start_request, uaf_obb_server_uri) # Request START_OBB uaf_obb_start_response = self.executePost(uaf_obb_server_uri, uaf_obb_start_request) if uaf_obb_start_response == None: return False print "UAF. Prepare for step 2. Get START response: '%s'" % uaf_obb_start_response uaf_obb_start_response_json = json.loads(uaf_obb_start_response) # Prepare STATUS_OBB #TODO: Remove needDetails parameter uaf_obb_status_request_dictionary = { "operation": "STATUS_%s" % uaf_obb_auth_method, "userName": user.getUserId(), "needDetails": 1, "oobStatusHandle": uaf_obb_start_response_json["oobStatusHandle"], } uaf_obb_status_request = json.dumps(uaf_obb_status_request_dictionary, separators=(',',':')) print "UAF. Prepare for step 2. Prepared STATUS request: '%s' to send to '%s'" % (uaf_obb_status_request, uaf_obb_server_uri) identity.setWorkingParameter("uaf_obb_auth_method", uaf_obb_auth_method) identity.setWorkingParameter("uaf_obb_server_uri", uaf_obb_server_uri) identity.setWorkingParameter("uaf_obb_start_response", uaf_obb_start_response) identity.setWorkingParameter("qr_image", uaf_obb_start_response_json["modeResult"]["qrCode"]["qrImage"]) identity.setWorkingParameter("uaf_obb_status_request", uaf_obb_status_request) return True else: return False
def process2FAPolicy(self, identity, foundUser, deviceInf, locationCriterion, deviceCriterion): skip2FA = False #Retrieve user's devices info devicesInfo = foundUser.getAttribute("oxTrustedDevicesInfo") #do geolocation geodata = self.getGeolocation(identity) if geodata == None: print "Casa. process2FAPolicy: Geolocation data not obtained. 2FA skipping based on location cannot take place" try: encService = CdiUtil.bean(EncryptionService) if devicesInfo == None: print "Casa. process2FAPolicy: There are no trusted devices for user yet" #Simulate empty list devicesInfo = "[]" else: devicesInfo = encService.decrypt(devicesInfo) devicesInfo = json.loads(devicesInfo) partialMatch = False idx = 0 #Try to find a match for device only for device in devicesInfo: partialMatch = device['browser']['name']==deviceInf['name'] and device['os']['version']==deviceInf['os']['version'] and device['os']['family']==deviceInf['os']['family'] if partialMatch: break idx+=1 matchFound = False #At least one of locationCriterion or deviceCriterion is True if locationCriterion and not deviceCriterion: #this check makes sense if there is city data only if geodata!=None: for device in devicesInfo: #Search all registered cities that are found in trusted devices for origin in device['origins']: matchFound = matchFound or origin['city']==geodata['city'] elif partialMatch: #In this branch deviceCriterion is True if not locationCriterion: matchFound = True elif geodata!=None: for origin in devicesInfo[idx]['origins']: matchFound = matchFound or origin['city']==geodata['city'] skip2FA = matchFound now = Date().getTime() #Update attribute oxTrustedDevicesInfo accordingly if partialMatch: #Update an existing record (update timestamp in city, or else add it) if geodata != None: partialMatch = False idxCity = 0 for origin in devicesInfo[idx]['origins']: partialMatch = origin['city']==geodata['city'] if partialMatch: break; idxCity+=1 if partialMatch: devicesInfo[idx]['origins'][idxCity]['timestamp'] = now else: devicesInfo[idx]['origins'].append({"city": geodata['city'], "country": geodata['country'], "timestamp": now}) else: #Create a new entry browser = {"name": deviceInf['name'], "version": deviceInf['version']} os = {"family": deviceInf['os']['family'], "version": deviceInf['os']['version']} if geodata == None: origins = [] else: origins = [{"city": geodata['city'], "country": geodata['country'], "timestamp": now}] obj = {"browser": browser, "os": os, "addedOn": now, "origins": origins} devicesInfo.append(obj) enc = json.dumps(devicesInfo, separators=(',',':')) enc = encService.encrypt(enc) identity.setWorkingParameter("trustedDevicesInfo", enc) except: print "Casa. process2FAPolicy. Error!", sys.exc_info()[1] return skip2FA
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 "U2F. Authenticate for step 1" 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 "U2F. Authenticate for step 2" token_response = ServerUtil.getFirstValue(requestParameters, "tokenResponse") if token_response == None: print "U2F. Authenticate for step 2. tokenResponse is empty" return False auth_method = ServerUtil.getFirstValue(requestParameters, "authMethod") if auth_method == None: print "U2F. Authenticate for step 2. authMethod is empty" 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 if (auth_method == 'authenticate'): print "U2F. Prepare for step 2. Call FIDO U2F in order to finish authentication workflow" authenticationRequestService = FidoU2fClientFactory.instance().createAuthenticationRequestService(self.metaDataConfiguration) authenticationStatus = authenticationRequestService.finishAuthentication(user.getUserId(), token_response) if (authenticationStatus.getStatus() != Constants.RESULT_SUCCESS): print "U2F. Authenticate for step 2. Get invalid authentication status from FIDO U2F server" return False return True elif (auth_method == 'enroll'): print "U2F. Prepare for step 2. Call FIDO U2F in order to finish registration workflow" registrationRequestService = FidoU2fClientFactory.instance().createRegistrationRequestService(self.metaDataConfiguration) registrationStatus = registrationRequestService.finishRegistration(user.getUserId(), token_response) if (registrationStatus.getStatus() != Constants.RESULT_SUCCESS): print "U2F. Authenticate for step 2. Get invalid registration status from FIDO U2F server" return False return True else: print "U2F. Prepare for step 2. Authenticatiod method is invalid" return False return False else: return False
def authenticate(self, configurationAttributes, requestParameters, step): userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() session_attributes = self.identity.getSessionId().getSessionAttributes() form_passcode = ServerUtil.getFirstValue(requestParameters, "passcode") print("SMPP form_response_passcode: {}".format(str(form_passcode))) if step == 1: print("SMPP Step 1 Password Authentication") credentials = self.identity.getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): logged_in = authenticationService.authenticate(user_name, user_password) if not logged_in: return False # Get the Person's number and generate a code foundUser = None try: foundUser = authenticationService.getAuthenticatedUser() except: print("SMPP Error retrieving user {} from LDAP".format(user_name)) return False mobile_number = None try: isVerified = foundUser.getAttribute("phoneNumberVerified") if isVerified: mobile_number = foundUser.getAttribute("employeeNumber") if not mobile_number: mobile_number = foundUser.getAttribute("mobile") if not mobile_number: mobile_number = foundUser.getAttribute("telephoneNumber") if not mobile_number: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to determine mobile phone number") print("SMPP Error finding mobile number for user '{}'".format(user_name)) return False except Exception as e: facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to determine mobile phone number") print("SMPP Error finding mobile number for {}: {}".format(user_name, e)) return False # Generate Random six digit code code = random.randint(100000, 999999) # Get code and save it in LDAP temporarily with special session entry self.identity.setWorkingParameter("code", code) self.identity.setWorkingParameter("mobile_number", mobile_number) self.identity.getSessionId().getSessionAttributes().put("mobile_number", mobile_number) if not self.sendMessage(mobile_number, str(code)): facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to send message to mobile phone") return False return True elif step == 2: # Retrieve the session attribute print("SMPP Step 2 SMS/OTP Authentication") code = session_attributes.get("code") print("SMPP Code: {}".format(str(code))) if code is None: print("SMPP Failed to find previously sent code") return False if form_passcode is None: print("SMPP Passcode is empty") return False if len(form_passcode) != 6: print("SMPP Passcode from response is not 6 digits: {}".format(form_passcode)) return False if form_passcode == code: print("SMPP SUCCESS! User entered the same code!") return True print("SMPP failed, user entered the wrong code! {} != {}".format(form_passcode, code)) facesMessages.add(facesMessage.SEVERITY_ERROR, "Incorrect SMS code, please try again.") return False print("SMPP ERROR: step param not found or != (1|2)") return False
def getCountAuthenticationSteps(self, configurationAttributes): identity = CdiUtil.bean(Identity) if (identity.isSetWorkingParameter("oxpush_count_login_steps")): return identity.getWorkingParameter("oxpush_count_login_steps") return 3
def getCountAuthenticationSteps(self, configurationAttributes): identity = CdiUtil.bean(Identity) if identity.isSetWorkingParameter("expDate"): return 2 else: return 1