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
Beispiel #2
0
    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
Beispiel #7
0
    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
Beispiel #14
0
 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
Beispiel #18
0
    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
Beispiel #24
0
    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
Beispiel #25
0
    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
Beispiel #26
0
    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