def init(self, configurationAttributes): print "Basic (lock account). Initialization" self.invalidLoginCountAttribute = "oxCountInvalidLogin" if configurationAttributes.containsKey("invalid_login_count_attribute"): self.invalidLoginCountAttribute = configurationAttributes.get("invalid_login_count_attribute").getValue2() else: print "Basic (lock account). Initialization. Using default attribute" self.maximumInvalidLoginAttemps = 3 if configurationAttributes.containsKey("maximum_invalid_login_attemps"): self.maximumInvalidLoginAttemps = StringHelper.toInteger(configurationAttributes.get("maximum_invalid_login_attemps").getValue2()) else: print "Basic (lock account). Initialization. Using default number attempts" self.lockExpirationTime = 180 if configurationAttributes.containsKey("lock_expiration_time"): self.lockExpirationTime = StringHelper.toInteger(configurationAttributes.get("lock_expiration_time").getValue2()) else: print "Basic (lock account). Initialization. Using default lock expiration time" print "Basic (lock account). Initialized successfully. invalid_login_count_attribute: '%s', maximum_invalid_login_attemps: '%s', lock_expiration_time: '%s'" % (self.invalidLoginCountAttribute, self.maximumInvalidLoginAttemps, self.lockExpirationTime) return True
def init(self, customScript, configurationAttributes): print "Basic (lock account). Initialization" self.invalidLoginCountAttribute = "oxCountInvalidLogin" if configurationAttributes.containsKey( "invalid_login_count_attribute"): self.invalidLoginCountAttribute = configurationAttributes.get( "invalid_login_count_attribute").getValue2() else: print "Basic (lock account). Initialization. Using default attribute" self.maximumInvalidLoginAttemps = 3 if configurationAttributes.containsKey( "maximum_invalid_login_attemps"): self.maximumInvalidLoginAttemps = StringHelper.toInteger( configurationAttributes.get( "maximum_invalid_login_attemps").getValue2()) else: print "Basic (lock account). Initialization. Using default number attempts" self.lockExpirationTime = 180 if configurationAttributes.containsKey("lock_expiration_time"): self.lockExpirationTime = StringHelper.toInteger( configurationAttributes.get( "lock_expiration_time").getValue2()) else: print "Basic (lock account). Initialization. Using default lock expiration time" print "Basic (lock account). Initialized successfully. invalid_login_count_attribute: '%s', maximum_invalid_login_attemps: '%s', lock_expiration_time: '%s'" % ( self.invalidLoginCountAttribute, self.maximumInvalidLoginAttemps, self.lockExpirationTime) return True
def getCountAuthenticationSteps(self, configurationAttributes): identity = CdiUtil.bean(Identity) if identity.isSetWorkingParameter("otp_count_login_steps"): return StringHelper.toInteger("%s" % identity.getWorkingParameter("otp_count_login_steps")) else: return 2
def getCountAuthenticationSteps(self, configurationAttributes): print "U2F. getCountAuthenticationSteps called" # To do any operations we need the identity variables available steps = 1 identity = CdiUtil.bean(Identity) if identity.isSetWorkingParameter("count_login_steps"): steps = StringHelper.toInteger( "%s" % identity.getWorkingParameter("count_login_steps")) print "U2F. getCountAuthenticationSteps returning %s" % steps return steps
def init(self, configurationAttributes): print "Cert. Initialization" if not (configurationAttributes.containsKey("chain_cert_file_path")): print "Cert. Initialization. Property chain_cert_file_path is mandatory" return False if not (configurationAttributes.containsKey("map_user_cert")): print "Cert. Initialization. Property map_user_cert is mandatory" return False chain_cert_file_path = configurationAttributes.get("chain_cert_file_path").getValue2() self.chain_certs = CertUtil.loadX509CertificateFromFile(chain_cert_file_path) if self.chain_certs == None: print "Cert. Initialization. Failed to load chain certificates from '%s'" % chain_cert_file_path return False print "Cert. Initialization. Loaded '%d' chain certificates" % self.chain_certs.size() crl_max_response_size = 5 * 1024 * 1024 # 10Mb if configurationAttributes.containsKey("crl_max_response_size"): crl_max_response_size = StringHelper.toInteger(configurationAttributes.get("crl_max_response_size").getValue2(), crl_max_response_size) print "Cert. Initialization. CRL max response size is '%d'" % crl_max_response_size # Define array to order methods correctly self.validator_types = [ 'generic', 'path', 'ocsp', 'crl'] self.validators = { 'generic' : [GenericCertificateVerifier(), False], 'path' : [PathCertificateVerifier(False), False], 'ocsp' : [OCSPCertificateVerifier(), False], 'crl' : [CRLCertificateVerifier(crl_max_response_size), False] } for type in self.validator_types: validator_param_name = "use_%s_validator" % type if configurationAttributes.containsKey(validator_param_name): validator_status = StringHelper.toBoolean(configurationAttributes.get(validator_param_name).getValue2(), False) self.validators[type][1] = validator_status print "Cert. Initialization. Validation method '%s' status: '%s'" % (type, self.validators[type][1]) self.map_user_cert = StringHelper.toBoolean(configurationAttributes.get("map_user_cert").getValue2(), False) print "Cert. Initialization. map_user_cert: '%s'" % self.map_user_cert self.enabled_recaptcha = self.initRecaptcha(configurationAttributes) print "Cert. Initialization. enabled_recaptcha: '%s'" % self.enabled_recaptcha print "Cert. Initialized successfully" return True
def init(self, customScript, configurationAttributes): print "Cert. Initialization" if not (configurationAttributes.containsKey("chain_cert_file_path")): print "Cert. Initialization. Property chain_cert_file_path is mandatory" return False if not (configurationAttributes.containsKey("map_user_cert")): print "Cert. Initialization. Property map_user_cert is mandatory" return False chain_cert_file_path = configurationAttributes.get("chain_cert_file_path").getValue2() self.chain_certs = CertUtil.loadX509CertificateFromFile(chain_cert_file_path) if self.chain_certs == None: print "Cert. Initialization. Failed to load chain certificates from '%s'" % chain_cert_file_path return False print "Cert. Initialization. Loaded '%d' chain certificates" % self.chain_certs.size() crl_max_response_size = 5 * 1024 * 1024 # 10Mb if configurationAttributes.containsKey("crl_max_response_size"): crl_max_response_size = StringHelper.toInteger(configurationAttributes.get("crl_max_response_size").getValue2(), crl_max_response_size) print "Cert. Initialization. CRL max response size is '%d'" % crl_max_response_size # Define array to order methods correctly self.validator_types = [ 'generic', 'path', 'ocsp', 'crl'] self.validators = { 'generic' : [GenericCertificateVerifier(), False], 'path' : [PathCertificateVerifier(False), False], 'ocsp' : [OCSPCertificateVerifier(), False], 'crl' : [CRLCertificateVerifier(crl_max_response_size), False] } for type in self.validator_types: validator_param_name = "use_%s_validator" % type if configurationAttributes.containsKey(validator_param_name): validator_status = StringHelper.toBoolean(configurationAttributes.get(validator_param_name).getValue2(), False) self.validators[type][1] = validator_status print "Cert. Initialization. Validation method '%s' status: '%s'" % (type, self.validators[type][1]) self.map_user_cert = StringHelper.toBoolean(configurationAttributes.get("map_user_cert").getValue2(), False) print "Cert. Initialization. map_user_cert: '%s'" % self.map_user_cert self.enabled_recaptcha = self.initRecaptcha(configurationAttributes) print "Cert. Initialization. enabled_recaptcha: '%s'" % self.enabled_recaptcha print "Cert. Initialized successfully" return True
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): 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 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) 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) 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) 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": # Modified for Casa compliance user_enrollments = self.findEnrollments(user_name, "hotp") #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 len(user_enrollments) > 0: 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) if find_user_by_external_uid != None: return True print "OTP. Process HOTP authentication during authentication. Failed to update user entry" user_enrollments = self.findEnrollments(user_name, "totp") if len(user_enrollments) > 0: for user_enrollment in user_enrollments: otp_secret_key = self.fromBase64Url(user_enrollment) # Validate TOTP validation_result = self.validateTotpKey( otp_secret_key, otpCode) 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 init(self, configurationAttributes): print "OTP (with lockout). Initialization" ############################################# ### OTP if not configurationAttributes.containsKey("otp_type"): print "OTP (with lockout). Initialization. Property otp_type is mandatory" return False self.otpType = configurationAttributes.get("otp_type").getValue2() if not self.otpType in ["hotp", "totp"]: print "OTP (with lockout). Initialization. Property value otp_type is invalid" return False if not configurationAttributes.containsKey("issuer"): print "OTP (with lockout). Initialization. Property issuer is mandatory" return False self.otpIssuer = configurationAttributes.get("issuer").getValue2() self.customLabel = None if configurationAttributes.containsKey("label"): self.customLabel = configurationAttributes.get("label").getValue2() self.customQrOptions = {} if configurationAttributes.containsKey("qr_options"): self.customQrOptions = configurationAttributes.get( "qr_options").getValue2() self.use_otp_group = False if configurationAttributes.containsKey("otp_group"): self.otp_group = configurationAttributes.get( "otp_group").getValue2() self.use_otp_group = True print "OTP (with lockout). Initialization. Using otp only if user belong to group: %s" % self.otp_group self.no_lockout_admin = "admin" if configurationAttributes.containsKey("no_lockout_admin"): self.no_lockout_admin = configurationAttributes.get( "no_lockout_admin").getValue2() if self.use_otp_group: if not configurationAttributes.containsKey("audit_attribute"): print "OTP (with lockout). Initialization. Property audit_attribute is not specified" return False else: self.audit_attribute = configurationAttributes.get( "audit_attribute").getValue2() self.registrationUri = None if configurationAttributes.containsKey("registration_uri"): self.registrationUri = configurationAttributes.get( "registration_uri").getValue2() validOtpConfiguration = self.loadOtpConfiguration( configurationAttributes) if not validOtpConfiguration: return False print "OTP (with lockout). Initialized successfully" ### OTP ############################################# ############################################# ### LOCKOUT self.invalidLoginCountAttribute = "oxCountInvalidLogin" if configurationAttributes.containsKey( "invalid_login_count_attribute"): self.invalidLoginCountAttribute = configurationAttributes.get( "invalid_login_count_attribute").getValue2() else: print "OTP (with lockout). Initialization. Using default attribute" self.maximumInvalidLoginAttemps = 3 if configurationAttributes.containsKey( "maximum_invalid_login_attemps"): self.maximumInvalidLoginAttemps = StringHelper.toInteger( configurationAttributes.get( "maximum_invalid_login_attemps").getValue2()) else: print "OTP (with lockout). Initialization. Using default number attempts" self.lockExpirationTime = 180 if configurationAttributes.containsKey("lock_expiration_time"): self.lockExpirationTime = StringHelper.toInteger( configurationAttributes.get( "lock_expiration_time").getValue2()) else: print "OTP (with lockout). Initialization. Using default lock expiration time" print "OTP (with lockout). Initialized successfully. invalid_login_count_attribute: '%s', maximum_invalid_login_attemps: '%s', lock_expiration_time: '%s'" % ( self.invalidLoginCountAttribute, self.maximumInvalidLoginAttemps, self.lockExpirationTime) ### LOCKOUT ############################################# return True
def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() self.setRequestScopedParameters(identity) if step == 1: ############################################# ### LOCKOUT print "OTP (with lockout). Authenticate for step 1" facesMessages = CdiUtil.bean(FacesMessages) facesMessages.setKeepMessages() identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() cacheService = CdiUtil.bean(CacheService) print "OTP (with lockout). Authenticate for step 1" authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user != None: self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(0)) elif user_name != self.no_lockout_admin: 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 "OTP (with lockout). Locking '%s' for '%s' seconds" % ( user_name, self.lockExpirationTime) self.lockUser(user_name, self.maximumInvalidLoginAttemps) return False if (countInvalidLogin >= self.maximumInvalidLoginAttemps ) and userSatus == "inactive": print "OTP (with lockout). 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 "OTP (with lockout). 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 "OTP (with lockout). 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 "OTP (with lockout). 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)) ### TODO: Fix free attempt after unlock authenticated_user = self.processBasicAuthentication( credentials) if authenticated_user == None: self.setUserAttributeValue( user_name, self.invalidLoginCountAttribute, StringHelper.toString(1)) if authenticated_user == None: return False ### LOCKOUT ############################################# # Check the otp_group user membership if (self.use_otp_group): print "OTP (with lockout). Authenticate for step 1. Checking if user '%s' belongs to otp_group" % authenticated_user.getUserId( ) is_member_otp_group = self.isUserMemberOfGroup( authenticated_user, self.audit_attribute, self.otp_group) if not is_member_otp_group: print "OTP (with lockout). Authenticate for step 1. User '%s' not a member of otp group, skipping OTP" % authenticated_user.getUserId( ) identity.setWorkingParameter("otp_count_login_steps", 1) return True else: print "OTP (with lockout). Authenticate for step 1. User '%s' is a member of otp group, continue to OTP" % authenticated_user.getUserId( ) 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 (with lockout). 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 (with lockout). Authenticate for step 1. Setting count steps: '%s'" % 3 identity.setWorkingParameter("otp_count_login_steps", 3) print "OTP (with lockout). 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 (with lockout). Authenticate for step 2" authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if user == None: print "OTP (with lockout). 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': auth_result = ServerUtil.getFirstValue(requestParameters, "auth_result") if not StringHelper.isEmpty(auth_result): print "OTP (with lockout). Authenticate for step 2. User not enrolled OTP" return False print "OTP (with lockout). 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 (with lockout). Authenticate for step 2. OTP authentication result: '%s'" % otp_auth_result return otp_auth_result elif step == 3: print "OTP (with lockout). Authenticate for step 3" authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if user == None: print "OTP (with lockout). 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 (with lockout). Authenticate for step 3. OTP authentication result: '%s'" % otp_auth_result return otp_auth_result else: return False
def update(self, dynamicScopeContext, configurationAttributes): print "Dynamic scope [claims_scope]. Update method" # Get the client and session and dynamic claims authorizationGrant = dynamicScopeContext.getAuthorizationGrant() oidcClient = authorizationGrant.getClient() currentEntityId = "oidc:%s" % oidcClient.getClientName() # sessionDn = authorizationGrant.getSessionDn() # print "Dynamic scope [claims_scope]. Got session DN = '%s'" % sessionDn # sessionId = dynamicScopeContext.getEntryAttributeValue(sessionDn, "sessionId") # if ( sessionDn != None ): # prepare the search results attributes claimNamesJsonString = None claimsSrcJsonString = None # then we look for the SAML persistentId value in user profile user = dynamicScopeContext.getUser() userTransientIds = user.getAttributeValues("transientId") if ( userTransientIds != None ): if ( userTransientIds.size > 0 ): # save latest time (set to 0 initially) latestExpiryTimeSec = 0 # go through existing user persistentIds for userTransientId in userTransientIds: # if the current RP already has a mapping then skip the second phase transientIdRp = StringHelper.split(userTransientId,'|')[0] if ( transientIdRp == currentEntityId ): print "Dynamic scope [claims_scope]. Found matching transientId '%s'" % userTransientId # Format is : currentOidcRp, expiryTimeSec, userInfoUrl, accessToken expiryTimeSec = StringHelper.split(userTransientId,'|')[1] userInfoUrl = StringHelper.split(userTransientId,'|')[2] accessToken = StringHelper.split(userTransientId,'|')[3] # Check the last timestamp is newer than the current one and not older than 15 minutes (900 second) expiryTimeSec = StringHelper.toInteger(expiryTimeSec) currenttimeSec = int(round(time.time())) if ( expiryTimeSec > latestExpiryTimeSec and expiryTimeSec > (currenttimeSec - 900) ): # Save expiry and update/set the _claim_sources parameters latestExpiryTimeSec = expiryTimeSec # create a JSON object with _claim_sources for distributed claims claimsSrcJsonString = '{"src1":{"endpoint":"%s","access_token":"%s"}}' % ( userInfoUrl, accessToken ) # Set the _claim_names value to the result - static as per PCTF ####################################################### # "_claim_names": { # "given_name": "src1", # "family_name": "src1", # "birthdate": "src1", # "address": "src1" # }, # create a JSON object with _claim_sources for distributed claims claimNamesJsonString = '{"given_name":"src1","family_name":"src1","birthdate":"src1","address":"src1"}' # set the claims if they have been found if ( claimNamesJsonString != None and claimsSrcJsonString != None ): # Get the claims object jsonWebResponse = dynamicScopeContext.getJsonWebResponse() claims = jsonWebResponse.getClaims() # create JSON objects claimNamesJson = JSONObject(claimNamesJsonString) claimsSrcJson = JSONObject(claimsSrcJsonString) # set the claims claims.setClaim("_claim_names", claimNamesJson) claims.setClaim("_claim_sources", claimsSrcJson) return True
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) 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) 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) 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) 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) 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