def sendDevicePushNotification(self, user, app_id, u2f_device, super_gluu_request): device_data = u2f_device.getDeviceData() if device_data == None: return {"send_android":0,"send_ios":0} platform = device_data.getPlatform() push_token = device_data.getPushToken() pushNotificationContext = PushNotificationContext(app_id,super_gluu_request) pushNotificationContext.debugEnabled = self.debugEnabled pushNotificationContext.user = user pushNotificationContext.u2fDevice = u2f_device pushNotificationContext.devicePlatform = platform pushNotificationContext.pushToken = push_token send_ios = 0 send_android = 0 if StringHelper.equalsIgnoreCase(platform,"ios") and StringHelper.isNotEmpty(push_token): # Sending notification to iOS user's device if self.pushAppleService == None: print "Super-Gluu-Push. Apple push notification service disabled" else: self.sendApplePushNotification(pushNotificationContext) send_ios = 1 if StringHelper.equalsIgnoreCase(platform,"android") and StringHelper.isNotEmpty(push_token): # Sending notification to android user's device if self.pushAndroidService == None: print "Super-Gluu-Push. Android push notification service disabled" else: self.sendAndroidPushNotification(pushNotificationContext) send_android = 1 return {"send_android":send_android,"send_ios":send_ios}
def processKeyStoreProperties(self, attrs): file = attrs.get("key_store_file") password = attrs.get("key_store_password") if file != None and password != None: file = file.getValue2() password = password.getValue2() if StringHelper.isNotEmpty(file) and StringHelper.isNotEmpty(password): self.keyStoreFile = file self.keyStorePassword = password return True print "Passport. readKeyStoreProperties. Properties key_store_file or key_store_password not found or empty" return False
def processKeyStoreProperties(self, attrs): file = attrs.get("key_store_file") password = attrs.get("key_store_password") if file != None and password != None: file = file.getValue2() password = password.getValue2() if StringHelper.isNotEmpty(file) and StringHelper.isNotEmpty( password): self.keyStoreFile = file self.keyStorePassword = password return True print "Passport. readKeyStoreProperties. Properties key_store_file or key_store_password not found or empty" return False
def createNewAuthenticatedSession(self, context, customParameters={}): sessionIdService = CdiUtil.bean(SessionIdService) user = context.getUser() client = CdiUtil.bean(Identity).getSessionClient().getClient() # Add mandatory session parameters sessionAttributes = HashMap() sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId()) sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId()) sessionAttributes.put(AuthorizeRequestParam.PROMPT, "") # Add custom session parameters for key, value in customParameters.iteritems(): if StringHelper.isNotEmpty(value): sessionAttributes.put(key, value) # Generate authenticated session sessionId = sessionIdService.generateAuthenticatedSessionId( context.getHttpRequest(), user.getDn(), sessionAttributes) print "ROPC script. Generated session id. DN: '%s'" % sessionId.getDn() return sessionId
def getGeolocation(self, identity): session_attributes = identity.getSessionId().getSessionAttributes() if session_attributes.containsKey("remote_ip"): remote_ip = session_attributes.get("remote_ip") if StringHelper.isNotEmpty(remote_ip): httpService = CdiUtil.bean(HttpService) http_client = httpService.getHttpsClient() http_client_params = http_client.getParams() http_client_params.setIntParameter( CoreConnectionPNames.CONNECTION_TIMEOUT, 4 * 1000) geolocation_service_url = "http://ip-api.com/json/%s?fields=country,city,status,message" % remote_ip geolocation_service_headers = {"Accept": "application/json"} try: http_service_response = httpService.executeGet( http_client, geolocation_service_url, geolocation_service_headers) http_response = http_service_response.getHttpResponse() except: print "Casa. Determine remote location. Exception: ", sys.exc_info( )[1] return None try: if not httpService.isResponseStastusCodeOk(http_response): print "Casa. Determine remote location. Get non 200 OK response from server:", str( http_response.getStatusLine().getStatusCode()) httpService.consume(http_response) return None response_bytes = httpService.getResponseContent( http_response) response_string = httpService.convertEntityToString( response_bytes, Charset.forName("UTF-8")) httpService.consume(http_response) finally: http_service_response.closeConnection() if response_string == None: print "Casa. Determine remote location. Get empty response from location server" return None response = json.loads(response_string) if not StringHelper.equalsIgnoreCase(response['status'], "success"): print "Casa. Determine remote location. Get response with status: '%s'" % response[ 'status'] return None return response return None
def getCodeFromRequest(self, requestParameters): print "MFA Recovery. getCodeFromRequest called" try: toBeFetched1 = "loginForm:recoveryCode1" toBeFetched2 = "loginForm:recoveryCode2" toBeFetched3 = "loginForm:recoveryCode3" code1 = ServerUtil.getFirstValue(requestParameters, toBeFetched1) code2 = ServerUtil.getFirstValue(requestParameters, toBeFetched2) code3 = ServerUtil.getFirstValue(requestParameters, toBeFetched3) print "MFA Recovery. getCodeFromRequest: fetched loginForm:recoveryCode(s) '%s-%s-%s'" % ( code1, code2, code3) if StringHelper.isNotEmpty(code1) and StringHelper.isNotEmpty( code2) and StringHelper.isNotEmpty(code3): code = "%s-%s-%s" % (code1, code2, code3) return code return Null except Exception, err: print("MFA Recovery. getCodeFromRequest Exception: " + str(err))
def processMappingCollectionFilters(self, attrs): param_idp = attrs.get("idp_to_collect_old_mappings_from") param_rps = attrs.get("rps_to_collect_old_mappings_for") self.idp_to_collect_old_mappings_from = [] self.rps_to_collect_old_mappings_for = [] # COLLECT - Parse the list of RPs and IDP that we need to collect for if param_idp != None and param_rps != None: idpList = param_idp.getValue2() rpList = param_rps.getValue2() if StringHelper.isNotEmpty(idpList) and StringHelper.isNotEmpty(rpList): self.idp_to_collect_old_mappings_from = StringHelper.split(idpList,',') self.rps_to_collect_old_mappings_for = StringHelper.split(rpList,',') print "Passport-saml. init. COLLECTING mappings for IDPs [ %s ]" % ', '.join(self.idp_to_collect_old_mappings_from) print "Passport-saml. init. COLLECTING mappings for RPs [ %s ]" % ', '.join(self.rps_to_collect_old_mappings_for) return True print "Passport-saml. init. NOT COLLECTING any mappings, parameters [idp_to_collect_old_mappings_from] and [rps_to_collect_old_mappings_for] missing/empty." return True
def sendDevicePushNotification(self, user, app_id, u2f_device, super_gluu_request): device_data = u2f_device.getDeviceData() if device_data == None: return {"send_android": 0, "send_ios": 0} platform = device_data.getPlatform() push_token = device_data.getPushToken() pushNotificationContext = PushNotificationContext( app_id, super_gluu_request) pushNotificationContext.debugEnabled = self.debugEnabled pushNotificationContext.user = user pushNotificationContext.u2fDevice = u2f_device pushNotificationContext.devicePlatform = platform pushNotificationContext.pushToken = push_token send_ios = 0 send_android = 0 if StringHelper.equalsIgnoreCase( platform, "ios") and StringHelper.isNotEmpty(push_token): # Sending notification to iOS user's device if self.pushAppleService == None: print "Super-Gluu-Push. Apple push notification service disabled" else: self.sendApplePushNotification(pushNotificationContext) send_ios = 1 if StringHelper.equalsIgnoreCase( platform, "android") and StringHelper.isNotEmpty(push_token): # Sending notification to android user's device if self.pushAndroidService == None: print "Super-Gluu-Push. Android push notification service disabled" else: self.sendAndroidPushNotification(pushNotificationContext) send_android = 1 return {"send_android": send_android, "send_ios": send_ios}
def getMfaValueFromAuth(self, requestParameters): print "MFA Chooser. getMfaValueFromAuth called" try: toBeFeatched = "loginForm:mfachoice" print "MFA Chooser. getMfaValueFromAuth: fetching '%s'" % toBeFeatched new_acr_value = ServerUtil.getFirstValue(requestParameters, toBeFeatched) print "MFA Chooser. getMfaValueFromAuth: fetched new_acr_value '%s'" % new_acr_value if StringHelper.isNotEmpty(new_acr_value): return new_acr_value return Null except Exception, err: print("MFA Chooser. getMfaValueFromAuth Exception: " + str(err))
def getAcrValueFromAuth(self, requestParameters): print "IDP Chooser. getAcrValueFromAuth called" try: toBeFeatched = "loginForm:acrname" print "IDP Chooser. getAcrValueFromAuth: fetching '%s'" % toBeFeatched new_acr_provider_value = ServerUtil.getFirstValue( requestParameters, toBeFeatched) print "IDP Chooser. getAcrValueFromAuth: fetched new_acr_provider_value '%s'" % new_acr_provider_value if StringHelper.isNotEmpty(new_acr_provider_value): return new_acr_provider_value return None except Exception, err: print("IDP Chooser. getAcrValueFromAuth Exception: " + str(err))
def alternateActionRequested(self, requestParameters): print "MFA Enroll Recovery. alternateActionRequested called" try: toBeFetched = "loginForm:action" print "MFA Enroll Recovery. alternateActionRequested: fetching '%s'" % toBeFetched action_value = ServerUtil.getFirstValue(requestParameters, toBeFetched) print "MFA Enroll Recovery. alternateActionRequested: fetched action_value '%s'" % action_value if ( StringHelper.isNotEmpty(action_value) ): return action_value return None except Exception, err: print("MFA Enroll Recovery. alternateActionRequested Exception: " + str(err)) return None
def getCustomAuthzParameter(self, simpleCustProperty): customAuthzParameter = None if simpleCustProperty != None: prop = simpleCustProperty.getValue2() if StringHelper.isNotEmpty(prop): customAuthzParameter = prop if customAuthzParameter == None: print "Passport. getCustomAuthzParameter. No custom param for OIDC authz request in script properties" print "Passport. getCustomAuthzParameter. Passport flow cannot be initiated by doing an OpenID connect authorization request" else: print "Passport. getCustomAuthzParameter. Custom param for OIDC authz request in script properties: %s" % customAuthzParameter return customAuthzParameter
def getGeolocation(self, identity): session_attributes = identity.getSessionId().getSessionAttributes() if session_attributes.containsKey("remote_ip"): remote_ip = session_attributes.get("remote_ip") if StringHelper.isNotEmpty(remote_ip): httpService = CdiUtil.bean(HttpService) http_client = httpService.getHttpsClient() http_client_params = http_client.getParams() http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 4 * 1000) geolocation_service_url = "http://ip-api.com/json/%s?fields=country,city,status,message" % remote_ip geolocation_service_headers = { "Accept" : "application/json" } try: http_service_response = httpService.executeGet(http_client, geolocation_service_url, geolocation_service_headers) http_response = http_service_response.getHttpResponse() except: print "Casa. Determine remote location. Exception: ", sys.exc_info()[1] return None try: if not httpService.isResponseStastusCodeOk(http_response): print "Casa. Determine remote location. Get non 200 OK response from server:", str(http_response.getStatusLine().getStatusCode()) httpService.consume(http_response) return None response_bytes = httpService.getResponseContent(http_response) response_string = httpService.convertEntityToString(response_bytes, Charset.forName("UTF-8")) httpService.consume(http_response) finally: http_service_response.closeConnection() if response_string == None: print "Casa. Determine remote location. Get empty response from location server" return None response = json.loads(response_string) if not StringHelper.equalsIgnoreCase(response['status'], "success"): print "Casa. Determine remote location. Get response with status: '%s'" % response['status'] return None return response return None
def updateUser(self, user, configurationAttributes): attributes = user.getCustomAttributes() # Add new attribute preferredLanguage attrPrefferedLanguage = GluuCustomAttribute("preferredLanguage", "en-us") attributes.add(attrPrefferedLanguage) # Add new attribute userPassword attrUserPassword = GluuCustomAttribute("userPassword", "test") attributes.add(attrUserPassword) # Update givenName attribute for attribute in attributes: attrName = attribute.getName() if (("givenname" == StringHelper.toLowerCase(attrName)) and StringHelper.isNotEmpty(attribute.getValue())): attribute.setValue(StringHelper.removeMultipleSpaces(attribute.getValue()) + " (updated)") return True
def updateUser(self, user, configurationAttributes): print "Cache refresh. UpdateUser method" attributes = user.getCustomAttributes() # Add new attribute preferredLanguage attrPrefferedLanguage = GluuCustomAttribute("preferredLanguage", "en-us") attributes.add(attrPrefferedLanguage) # Add new attribute userPassword attrUserPassword = GluuCustomAttribute("userPassword", "test") attributes.add(attrUserPassword) # Update givenName attribute for attribute in attributes: attrName = attribute.getName() if (("givenname" == StringHelper.toLowerCase(attrName)) and StringHelper.isNotEmpty(attribute.getValue())): attribute.setValue(StringHelper.removeMultipleSpaces(attribute.getValue()) + " (updated)") return True
def getCurrentSamlConfiguration(self, currentSamlConfiguration, configurationAttributes, requestParameters): saml_client_configuration = self.getClientConfiguration( configurationAttributes, requestParameters) if saml_client_configuration == None: return currentSamlConfiguration saml_client_configuration_value = json.loads( saml_client_configuration.getValue()) client_asimba_saml_certificate = None client_asimba_saml_certificate_file = saml_client_configuration_value[ "asimba_saml_certificate_file"] if StringHelper.isNotEmpty(client_asimba_saml_certificate_file): client_asimba_saml_certificate = self.loadCeritificate( client_asimba_saml_certificate_file) if StringHelper.isEmpty(client_asimba_saml_certificate): print "Asimba. BuildClientSamlConfiguration. File with x509 certificate should be not empty. Using default configuration" return currentSamlConfiguration clientSamlConfiguration = currentSamlConfiguration.clone() if client_asimba_saml_certificate != None: clientSamlConfiguration.loadCertificateFromString( client_asimba_saml_certificate) client_asimba_entity_id = saml_client_configuration_value[ "asimba_entity_id"] clientSamlConfiguration.setIssuer(client_asimba_entity_id) saml_use_authn_context = saml_client_configuration_value[ "saml_use_authn_context"] client_use_saml_use_authn_context = StringHelper.toBoolean( saml_use_authn_context, True) clientSamlConfiguration.setUseRequestedAuthnContext( client_use_saml_use_authn_context) return clientSamlConfiguration
def authenticate(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) saml_map_user = False saml_enroll_user = False saml_enroll_all_user_attr = False # Use saml_deployment_type only if there is no attributes mapping if configurationAttributes.containsKey("saml_deployment_type"): saml_deployment_type = StringHelper.toLowerCase(configurationAttributes.get("saml_deployment_type").getValue2()) if StringHelper.equalsIgnoreCase(saml_deployment_type, "map"): saml_map_user = True if StringHelper.equalsIgnoreCase(saml_deployment_type, "enroll"): saml_enroll_user = True if StringHelper.equalsIgnoreCase(saml_deployment_type, "enroll_all_attr"): saml_enroll_all_user_attr = True saml_allow_basic_login = False if configurationAttributes.containsKey("saml_allow_basic_login"): saml_allow_basic_login = StringHelper.toBoolean(configurationAttributes.get("saml_allow_basic_login").getValue2(), False) use_basic_auth = False if saml_allow_basic_login: # Detect if user used basic authnetication method user_name = credentials.getUsername() user_password = credentials.getPassword() if StringHelper.isNotEmpty(user_name) and StringHelper.isNotEmpty(user_password): use_basic_auth = True if (step == 1) and saml_allow_basic_login and use_basic_auth: print "Asimba. Authenticate for step 1. Basic authentication" identity.setWorkingParameter("saml_count_login_steps", 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 return True if (step == 1): print "Asimba. Authenticate for step 1" currentSamlConfiguration = self.getCurrentSamlConfiguration(self.samlConfiguration, configurationAttributes, requestParameters) if (currentSamlConfiguration == None): print "Asimba. Prepare for step 1. Client saml configuration is invalid" return False saml_response_array = requestParameters.get("SAMLResponse") if ArrayHelper.isEmpty(saml_response_array): print "Asimba. Authenticate for step 1. saml_response is empty" return False saml_response = saml_response_array[0] print "Asimba. Authenticate for step 1. saml_response: '%s'" % saml_response samlResponse = Response(currentSamlConfiguration) samlResponse.loadXmlFromBase64(saml_response) saml_validate_response = True if configurationAttributes.containsKey("saml_validate_response"): saml_validate_response = StringHelper.toBoolean(configurationAttributes.get("saml_validate_response").getValue2(), False) if saml_validate_response: if not samlResponse.isValid(): print "Asimba. Authenticate for step 1. saml_response isn't valid" return False if samlResponse.isAuthnFailed(): print "Asimba. Authenticate for step 1. saml_response AuthnFailed" return False saml_response_attributes = samlResponse.getAttributes() print "Asimba. Authenticate for step 1. attributes: '%s'" % saml_response_attributes if saml_map_user: saml_user_uid = self.getSamlNameId(samlResponse) if saml_user_uid == None: return False # Use mapping to local IDP user print "Asimba. Authenticate for step 1. Attempting to find user by oxExternalUid: saml: '%s'" % saml_user_uid # Check if the is user with specified saml_user_uid find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) if find_user_by_uid == None: print "Asimba. Authenticate for step 1. Failed to find user" print "Asimba. Authenticate for step 1. Setting count steps to 2" identity.setWorkingParameter("saml_count_login_steps", 2) identity.setWorkingParameter("saml_user_uid", saml_user_uid) return True found_user_name = find_user_by_uid.getUserId() print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name user_authenticated = authenticationService.authenticate(found_user_name) if user_authenticated == False: print "Asimba. Authenticate for step 1. Failed to authenticate user" return False print "Asimba. Authenticate for step 1. Setting count steps to 1" identity.setWorkingParameter("saml_count_login_steps", 1) post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result return post_login_result elif saml_enroll_user: # Convert SAML response to user entry newUser = self.getMappedUser(configurationAttributes, requestParameters, saml_response_attributes) saml_user_uid = self.getNameId(samlResponse, newUser) if saml_user_uid == None: return False self.setDefaultUid(newUser, saml_user_uid) newUser.setAttribute("oxExternalUid", "saml:%s" % saml_user_uid) # Use auto enrollment to local IDP print "Asimba. Authenticate for step 1. Attempting to find user by oxExternalUid: saml: '%s'" % saml_user_uid # Check if there is user with specified saml_user_uid find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) if find_user_by_uid == None: # Auto user enrollment print "Asimba. Authenticate for step 1. There is no user in LDAP. Adding user to local LDAP" print "Asimba. Authenticate for step 1. Attempting to add user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) user_unique = self.checkUserUniqueness(newUser) if not user_unique: print "Asimba. Authenticate for step 1. Failed to add user: '******'. User not unique" % newUser.getUserId() facesMessages = CdiUtil.bean(FacesMessages) facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to enroll. User with same key attributes exist already") facesMessages.setKeepMessages() return False find_user_by_uid = userService.addUser(newUser, True) print "Asimba. Authenticate for step 1. Added new user with UID: '%s'" % find_user_by_uid.getUserId() else: if self.updateUser: print "Asimba. Authenticate for step 1. Attempting to update user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) find_user_by_uid.setCustomAttributes(newUser.getCustomAttributes()) userService.updateUser(find_user_by_uid) print "Asimba. Authenticate for step 1. Updated user with UID: '%s'" % saml_user_uid found_user_name = find_user_by_uid.getUserId() print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name user_authenticated = authenticationService.authenticate(found_user_name) if user_authenticated == False: print "Asimba. Authenticate for step 1. Failed to authenticate user: '******'" % found_user_name return False print "Asimba. Authenticate for step 1. Setting count steps to 1" identity.setWorkingParameter("saml_count_login_steps", 1) post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result return post_login_result elif saml_enroll_all_user_attr: # Convert SAML response to user entry newUser = self.getMappedAllAttributesUser(saml_response_attributes) saml_user_uid = self.getNameId(samlResponse, newUser) if saml_user_uid == None: return False self.setDefaultUid(newUser, saml_user_uid) newUser.setAttribute("oxExternalUid", "saml:%s" % saml_user_uid) print "Asimba. Authenticate for step 1. Attempting to find user by oxExternalUid: saml:%s" % saml_user_uid # Check if there is user with specified saml_user_uid find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) if find_user_by_uid == None: # Auto user enrollment print "Asimba. Authenticate for step 1. There is no user in LDAP. Adding user to local LDAP" print "Asimba. Authenticate for step 1. Attempting to add user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) user_unique = self.checkUserUniqueness(newUser) if not user_unique: print "Asimba. Authenticate for step 1. Failed to add user: '******'. User not unique" % newUser.getUserId() facesMessages = CdiUtil.bean(FacesMessages) facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to enroll. User with same key attributes exist already") facesMessages.setKeepMessages() return False find_user_by_uid = userService.addUser(newUser, True) print "Asimba. Authenticate for step 1. Added new user with UID: '%s'" % find_user_by_uid.getUserId() else: if self.updateUser: print "Asimba. Authenticate for step 1. Attempting to update user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) find_user_by_uid.setCustomAttributes(newUser.getCustomAttributes()) userService.updateUser(find_user_by_uid) print "Asimba. Authenticate for step 1. Updated user with UID: '%s'" % saml_user_uid found_user_name = find_user_by_uid.getUserId() print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name user_authenticated = authenticationService.authenticate(found_user_name) if user_authenticated == False: print "Asimba. Authenticate for step 1. Failed to authenticate user" return False print "Asimba. Authenticate for step 1. Setting count steps to 1" identity.setWorkingParameter("saml_count_login_steps", 1) post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result return post_login_result else: if saml_user_uid == None: return False # Check if the is user with specified saml_user_uid print "Asimba. Authenticate for step 1. Attempting to find user by uid: '%s'" % saml_user_uid find_user_by_uid = userService.getUser(saml_user_uid) if find_user_by_uid == None: print "Asimba. Authenticate for step 1. Failed to find user" return False found_user_name = find_user_by_uid.getUserId() print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name user_authenticated = authenticationService.authenticate(found_user_name) if user_authenticated == False: print "Asimba. Authenticate for step 1. Failed to authenticate user" return False print "Asimba. Authenticate for step 1. Setting count steps to 1" identity.setWorkingParameter("saml_count_login_steps", 1) post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result return post_login_result elif (step == 2): print "Asimba. Authenticate for step 2" sessionAttributes = identity.getSessionId().getSessionAttributes() if (sessionAttributes == None) or not sessionAttributes.containsKey("saml_user_uid"): print "Asimba. Authenticate for step 2. saml_user_uid is empty" return False saml_user_uid = sessionAttributes.get("saml_user_uid") passed_step1 = StringHelper.isNotEmptyString(saml_user_uid) if not passed_step1: return False 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 saml_user_uid # Avoid mapping Saml account to more than one IDP account find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) if find_user_by_uid == None: # Add saml_user_uid to user one id UIDs find_user_by_uid = userService.addUserAttribute(user_name, "oxExternalUid", "saml:%s" % saml_user_uid) if find_user_by_uid == None: print "Asimba. Authenticate for step 2. Failed to update current user" return False post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) print "Asimba. Authenticate for step 2. post_login_result: '%s'" % post_login_result return post_login_result else: found_user_name = find_user_by_uid.getUserId() print "Asimba. Authenticate for step 2. found_user_name: '%s'" % found_user_name if StringHelper.equals(user_name, found_user_name): post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) print "Asimba. Authenticate for step 2. post_login_result: '%s'" % post_login_result return post_login_result return False else: return False
def authenticate(self, configurationAttributes, requestParameters, step): print "Casa. authenticate %s" % str(step) userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) if step == 1: # Determine if external provider must be used provider = ServerUtil.getFirstValue(requestParameters, "loginForm:provider") if StringHelper.isNotEmpty(provider): url = self.getAuthzRequestUrl(provider) if url != None: CdiUtil.bean(FacesService).redirectToExternalURL(url) return url != None 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) mfaOff = foundUser.getAttribute("oxPreferredMethod") == None logged_in = False if mfaOff: logged_in = authenticationService.authenticate(user_name, user_password) else: acr = self.getSuitableAcr(foundUser, platform_data['isMobile']) if acr != None: module = self.authenticators[acr] logged_in = module.authenticate(module.configAttrs, requestParameters, step) if logged_in: foundUser = authenticationService.getAuthenticatedUser() if foundUser == None: print "Casa. authenticate for step 1. Cannot retrieve logged user" else: if mfaOff: identity.setWorkingParameter("skip2FA", True) else: #Determine whether to skip 2FA based on policy defined (global or user custom) skip2FA = self.determineSkip2FA(userService, identity, foundUser, platform_data) identity.setWorkingParameter("skip2FA", skip2FA) identity.setWorkingParameter("ACR", acr) return True else: print "Casa. authenticate for step 1 was not successful" return False else: user = authenticationService.getAuthenticatedUser() if user == None: print "Casa. authenticate for step 2. Cannot retrieve logged user" return False #see casa.xhtml alter = ServerUtil.getFirstValue(requestParameters, "alternativeMethod") if alter != None: #bypass the rest of this step if an alternative method was provided. Current step will be retried (see getNextStep) self.simulateFirstStep(requestParameters, alter) return True session_attributes = identity.getSessionId().getSessionAttributes() acr = session_attributes.get("ACR") #this working parameter is used in casa.xhtml identity.setWorkingParameter("methods", ArrayList(self.getAvailMethodsUser(user, acr))) success = False if acr in self.authenticators: module = self.authenticators[acr] success = module.authenticate(module.configAttrs, requestParameters, step) #Update the list of trusted devices if 2fa passed if success: print "Casa. authenticate. 2FA authentication was successful" tdi = session_attributes.get("trustedDevicesInfo") if tdi == None: print "Casa. authenticate. List of user's trusted devices was not updated" else: user.setAttribute("oxTrustedDevicesInfo", tdi) userService.updateUser(user) else: print "Casa. authenticate. 2FA authentication failed" return success return False
def prepareForStep(self, configurationAttributes, requestParameters, step): print "IDP Chooser. prepareForStep called for step '%s'" % step identity = CdiUtil.bean(Identity) sessionId = identity.getSessionId() sessionAttributes = sessionId.getSessionAttributes() entityId = sessionAttributes.get("entityId") entitySpNameQualifier = sessionAttributes.get("spNameQualifier") # entityId is used for UI branding. Handle getting entityId if it's an OIDC client if (entityId == None): # First get the client_id (should be deterministic ... ?????) currentClientId = sessionAttributes.get("client_id") # Call the ClientService and get all clients clientService = CdiUtil.bean(ClientService) oidcClient = clientService.getClient(currentClientId) if (oidcClient != None): entityId = "oidc:%s" % oidcClient.getClientName() sessionAttributes.put("entityId", entityId) # SpNameQualifier is used for persistenId generation. Handle getting entitySpNameQualifier if it's an OIDC client if (entitySpNameQualifier == None): # Look for value saved in the PolicyURL field in the client configurationAttributes clientPolicyUri = oidcClient.getPolicyUri() if (StringHelper.isNotEmpty(clientPolicyUri)): # Set it to the clientPolicyUri if absent entitySpNameQualifier = clientPolicyUri sessionAttributes.put("spNameQualifier", clientPolicyUri) # FIXME - For now as an error scenario if it's not found put a default if (entityId == None): entityId = "_default" # CUSTOMIZATION - Select which page body elements will be rendered if (sessionAttributes.get("pageContent") == None): # CUSTOMIZATION - FIRST try direct match pageContent = self.selectorPageContent.get(entityId) # CUSTOMIZATION - SECOND try prefix match if (pageContent == None): for contentKey in self.selectorPageContent.keys(): if (entityId.find(contentKey) == 0): pageContent = self.selectorPageContent.get(contentKey) # CUSTOMIZATION - LASTLY go to default content if (pageContent == None): pageContent = self.selectorPageContent.get("_default") # CUSTOMIZATION - save the page content in session for reference in xhtml pages if (pageContent != None): sessionAttributes.put("pageContent", pageContent) else: # We have an error - log it and fail print "IDP Chooser. prepareForStep ERROR: '_default' and '%s' page content missing in file " % ( entityId, configurationAttributes.get( "selector_page_content_file").getValue2()) return False # CUSTOMIZATION - Select which credential buttons will show up showCredentials = sessionAttributes.get( "pageContent")["credentials"] allCredentials = self.selectorPageContent["_default"][ "credentials"] for cred in StringHelper.split(allCredentials, ','): if (showCredentials.find(cred) == -1): sessionAttributes.put("hide_cred_" + cred, False) # SWITCH - update switch flow step if coming back with a user if (sessionAttributes.get("switchFlowStatus") == "1_GET_SOURCE" and sessionAttributes.get("auth_user") != None): # first get the source user and validate the persistentId exists for the entitySpNameQualifier userService = CdiUtil.bean(UserService) sourceUser = userService.getUser( sessionAttributes.get("switchSourceAuthenticatedUser")) # then find the persistenId for the entitySpNameQualifier in the source user sourcePersistentIds = sourceUser.getAttributeValues("persistentId") if (sourcePersistentIds != None): # go through source user persistentIds for userPersistentId in sourcePersistentIds: existingMappedRp = StringHelper.split( userPersistentId, '|')[0] # if the current RP matches, save the persistenId for the target if (userPersistentId.find(entitySpNameQualifier) > -1): sessionAttributes.put("switchPersistentId", userPersistentId) print "IDP Chooser. prepareForStep SWITCH FLOW: setting 2_GET_TARGET" sessionAttributes.put("switchFlowStatus", "2_GET_TARGET") # SWITCH - move to switch screen if the target has been authenticated elif (sessionAttributes.get("switchFlowStatus") == "2_GET_TARGET" and sessionAttributes.get("auth_user") != None): # first get the target user userService = CdiUtil.bean(UserService) targetUser = userService.getUser( sessionAttributes.get("switchTargetAuthenticatedUser")) # then find the persistenId for the entitySpNameQualifier in the target user targetPersistentIds = targetUser.getAttributeValues("persistentId") switchCurrentState = "AVAILABLE" if (targetPersistentIds != None): # go through source user persistentIds for userPersistentId in targetPersistentIds: existingMappedRp = StringHelper.split( userPersistentId, '|')[0] # if the current RP already has a persistentId then mark it if (entitySpNameQualifier != None and userPersistentId.find(entitySpNameQualifier) > -1): switchCurrentState = "NOT AVAILABLE - Persistent ID already exists for this RP in the target" if (switchCurrentState == "AVAILABLE"): print "IDP Chooser. prepareForStep SWITCH FLOW: setting 3_DO_SWITCH" sessionAttributes.put("switchFlowStatus", "3_DO_SWITCH") else: print "IDP Chooser. prepareForStep SWITCH FLOW: FAILED - target contains mapping for %s" % entitySpNameQualifier sessionAttributes.put("switchFlowStatus", "4_FINISHED") sessionAttributes.put("switchCurrentState", switchCurrentState) # MFA - update mfa flow status - check if the entityId is on the list of MFA applications mfaFlowStatus = sessionAttributes.get("mfaFlowStatus") print "IDP Chooser. prepareForStep Fetched mfaFlowStatus = '%s'" % mfaFlowStatus for mfaEntityId in StringHelper.split(self.entityids_with_mfa, ','): if (mfaEntityId == entityId): # if the status is blank then we set it to MFA_1_REQUIRED. This also means first pass so no MFA forwarding if (mfaFlowStatus == None): mfaFlowStatus = "MFA_1_REQUIRED" print "IDP Chooser. prepareForStep Setting mfaFlowStatus = '%s'" % mfaFlowStatus sessionAttributes.put("mfaFlowStatus", mfaFlowStatus) # we check that we have an authenticated user, which is a signal to trigger MFA elif (sessionAttributes.get("auth_user") != None): print "IDP Chooser. prepareForStep For mfaFlowStatus found authenticated user = '******'" % sessionAttributes.get( "auth_user") # SWITCH - we check that we are not in a switch flow, or switch flow has finished switchFlowStatus = sessionAttributes.get( "switchSourceAuthenticatedUser") if (switchFlowStatus == None or switchFlowStatus == "4_FINISHED"): mfaFlowStatus = "MFA_2_IN_PROGRESS" print "IDP Chooser. prepareForStep Setting mfaFlowStatus = '%s' and [new_acr_value to 'passport_social'] and [selectedProvider to 'mfa']" % mfaFlowStatus sessionAttributes.put("mfaFlowStatus", mfaFlowStatus) print "IDP Chooser. prepareForStep Setting [new_acr_value = 'passport_social'] and [selectedProvider = 'mfa']" identity.setWorkingParameter("new_acr_value", "passport_social") sessionAttributes.put("selectedProvider", "mfa") ## SESSION_SAFE - update CdiUtil.bean(SessionIdService).updateSessionId(sessionId) print "IDP Chooser. prepareForStep. got session '%s'" % identity.getSessionId( ).toString() if (step == 1 or step == 2): return True else: return False
def getTargetEndpointArn(self, platform, pushNotificationContext): deviceRegistrationService = pushNotificationContext.deviceRegistrationService pushSnsService = pushNotificationContext.pushSnsService user = pushNotificationContext.user u2fDevice = pushNotificationContext.u2fDevice targetEndpointArn = None # Return endpoint ARN if it is created already notificationConf = u2fDevice.getDeviceNotificationConf() if StringHelper.isNotEmpty(notificationConf): notificationConfJson = json.loads(notificationConf) targetEndpointArn = notificationConfJson['sns_endpoint_arn'] if StringHelper.isNotEmpty(targetEndpointArn): print "Super-Gluu-Push. Target endpoint ARN already created : ", targetEndpointArn return targetEndpointArn # Create endpoint ARN pushClient = None pushClientAuth = None platformApplicationArn = None if platform == PushPlatform.GCM: pushClient = self.pushAndroidService if self.pushSnsMode: platformApplicationArn = self.pushAndroidPlatformArn if self.pushGluuMode: pushClientAuth = self.pushAndroidServiceAuth elif platform == PushPlatform.APNS: pushClient = self.pushAppleService if self.pushSnsMode: platformApplicationArn = self.pushApplePlatformArn if self.pushGluuMode: pushClientAuth = self.pushAppleServiceAuth else: print "Super-Gluu-Push. Unsupported platform for ARN." return None deviceData = u2fDevice.getDeviceData() pushToken = deviceData.getPushToken() print "Super-Gluu-Push. Attempting to create target endpoint ARN for user: %s" % user.getUserId( ) if self.pushSnsMode: targetEndpointArn = pushSnsService.createPlatformArn( pushClient, platformApplicationArn, pushToken, user) else: customUserData = pushSnsService.getCustomUserData(user) registerDeviceResponse = pushClient.registerDevice( pushClientAuth, pushToken, customUserData) if registerDeviceResponse != None and registerDeviceResponse.getStatusCode( ) == 200: targetEndpointArn = registerDeviceResponse.getEndpointArn() if StringHelper.isEmpty(targetEndpointArn): print "Super-Gluu-Push. Failed to get endpoint ARN for user: '******'" % user.getUserId( ) return None printmsg = "Super-Gluu-Push. Create target endpoint ARN '%s' for user '%s'" print printmsg % (targetEndpointArn, user.getUserId()) # Store created endpoint ARN in device entry userInum = user.getAttribute("inum") u2fDeviceUpdate = deviceRegistrationService.findUserDeviceRegistration( userInum, u2fDevice.getId()) u2fDeviceUpdate.setDeviceNotificationConf( '{"sns_endpoint_arn": "%s"}' % targetEndpointArn) deviceRegistrationService.updateDeviceRegistration( userInum, u2fDeviceUpdate) return targetEndpointArn
def prepareForStep(self, configurationAttributes, requestParameters, step): if REMOTE_DEBUG: pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True) # Inject dependencies identity = CdiUtil.bean(Identity) facesResources = CdiUtil.bean(FacesResources) facesService = CdiUtil.bean(FacesService) userService = CdiUtil.bean(UserService) session = identity.getSessionId() sessionAttributes = session.getSessionAttributes() externalContext = facesResources.getFacesContext().getExternalContext() uiLocales = sessionAttributes.get(AuthorizeRequestParam.UI_LOCALES) rpConfig = self.getRPConfig(session) clientUri = self.getClientUri(session) externalContext.addResponseHeader( "Content-Security-Policy", "default-src 'self' https://www.canada.ca; font-src 'self' https://fonts.gstatic.com https://use.fontawesome.com https://www.canada.ca; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline' https://use.fontawesome.com https://fonts.googleapis.com https://www.canada.ca; script-src 'self' 'unsafe-inline' https://www.canada.ca https://ajax.googleapis.com; connect-src 'self' https://*.fjgc-gccf.gc.ca" ) if step == 1: httpRequest = externalContext.getRequest() # Bookmark detection #if httpRequest.getHeader("referer") is None: # if StringHelper.isNotEmpty(clientUri): # facesService.redirectToExternalURL(clientUri) # return True # else: # print("%s: prepareForStep. clientUri is missing for client %s" % (self.name, self.getClient(session).getClientName())) # return False # forceAuthn workaround prompt2 = httpRequest.getParameter("prompt2") if prompt2 == "login": identity.setWorkingParameter("forceAuthn", True) # step could actually be 2, or 3 if uiLocales is not None: if len(self.providers) > 1: step = self.STEP_CHOOSER else: step = self.STEP_1FA if identity.getWorkingParameter("abort"): # Back button workaround # Obtain the client URI of the current client from the client configuration if len(self.providers ) == 1: # Pass through, so send them back to the client if StringHelper.isNotEmpty(clientUri): facesService.redirectToExternalURL(clientUri) return True else: print( "%s: prepareForStep. clientUri is missing for client %s" % (self.name, self.getClient(session).getClientName())) return False else: # reset the chooser identity.setWorkingParameter("provider", None) if step == self.STEP_CHOOSER: # Prepare for chooser page customization. for param in ["layout", "chooser", "content"]: identity.setWorkingParameter(param, rpConfig[param]) elif step in {self.STEP_1FA, self.STEP_COLLECT, self.STEP_2FA}: # Passport passportOptions = { "ui_locales": uiLocales, "exp": int(time.time()) + 60 } if step in {self.STEP_1FA, self.STEP_COLLECT}: provider = identity.getWorkingParameter("provider") if provider is None and len( self.providers ) == 1: # Only one provider. Direct Pass-through provider = next(iter(self.providers)) identity.setWorkingParameter("provider", provider) if step == self.STEP_1FA: # Coordinate single-sign-on (SSO) maxAge = (sessionAttributes.get(AuthorizeRequestParam.MAX_AGE) or self.getClient(session).getDefaultMaxAge()) if (identity.getWorkingParameter("forceAuthn") or ("GCCF" in self.passport.getProvider(provider)["options"] and maxAge < 1200) ): # 1200 is 20 minutes, the SSO timeout on GCKey and CBS passportOptions["forceAuthn"] = "true" elif step == self.STEP_COLLECT: collect = rpConfig.get("collect") if collect is not None: passportOptions["allowCreate"] = rpConfig.get( "allowCreate") or "false" passportOptions["spNameQualifier"] = collect else: # This should never happen print( "%s. prepareForStep: collection entityID is missing" % self.name) return False elif step == self.STEP_2FA: provider = rpConfig.get("mfaProvider") if provider is None: print("%s: prepareForStep. mfaProvider is missing!" % self.name) return False mfaId = identity.getWorkingParameter("mfaId") if mfaId is None: print("%s: prepareForStep. mfaId is missing!" % self.name) return False else: passportOptions["login_hint"] = mfaId # The following parameters are redundant, but currently required by the 2ndFaaS passportOptions[ "redirect_uri"] = self.passport.getProvider( provider)["callbackUrl"] passportOptions["response_type"] = "code" passportOptions["scope"] = "openid profile" # Set the abort flag to handle back button identity.setWorkingParameter("abort", True) # Send the request to passport passportRequest = self.passport.createRequest( provider, passportOptions) facesService.redirectToExternalURL(passportRequest) elif step in {self.STEP_FIDO_REGISTER, self.STEP_FIDO_AUTH}: userId = identity.getWorkingParameter("userId") metaDataConfiguration = self.getFidoMetaDataConfiguration() if step == self.STEP_FIDO_REGISTER: try: attestationService = Fido2ClientFactory.instance( ).createAttestationService(metaDataConfiguration) attestationRequest = json.dumps( { 'username': userId, 'displayName': userId, 'attestation': 'direct', 'timeout': 120000, 'userVerification': 'discouraged' }, separators=(',', ':')) attestationResponse = attestationService.register( attestationRequest).readEntity(java.lang.String) except ClientErrorException as ex: print( "%s. Prepare for step. Failed to start FIDO2 attestation flow. Exception:" % self.name, sys.exc_info()[1]) return False identity.setWorkingParameter( "fido2_attestation_request", ServerUtil.asJson(attestationResponse)) print(ServerUtil.asJson(attestationResponse)) elif step == self.STEP_FIDO_AUTH: userId = identity.getWorkingParameter("userId") metaDataConfiguration = self.getFidoMetaDataConfiguration() fidoDeviceCount = userService.countFidoAndFido2Devices( userId, self.fido2_domain) try: assertionService = Fido2ClientFactory.instance( ).createAssertionService(metaDataConfiguration) assertionRequest = json.dumps( { 'username': userId, 'timeout': 120000, 'userVerification': 'discouraged' }, separators=(',', ':')) assertionResponse = assertionService.authenticate( assertionRequest).readEntity(java.lang.String) except ClientErrorException as ex: print( "%s. Prepare for step. Failed to start FIDO2 assertion flow. Exception:" % self.name, sys.exc_info()[1]) return False identity.setWorkingParameter( "fido2_assertion_request", ServerUtil.asJson(assertionResponse)) return True
def getTargetEndpointArn(self, platform, pushNotificationContext): deviceRegistrationService = pushNotificationContext.deviceRegistrationService pushSnsService = pushNotificationContext.pushSnsService user = pushNotificationContext.user u2fDevice = pushNotificationContext.u2fDevice targetEndpointArn = None # Return endpoint ARN if it is created already notificationConf = u2fDevice.getDeviceNotificationConf() if StringHelper.isNotEmpty(notificationConf): notificationConfJson = json.loads(notificationConf) targetEndpointArn = notificationConfJson['sns_endpoint_arn'] if StringHelper.isNotEmpty(targetEndpointArn): print "Super-Gluu-Push. Target endpoint ARN already created : ", targetEndpointArn return targetEndpointArn # Create endpoint ARN pushClient = None pushClientAuth = None platformApplicationArn = None if platform == PushPlatform.GCM: pushClient = self.pushAndroidService if self.pushSnsMode: platformApplicationArn = self.pushAndroidPlatformArn if self.pushGluuMode: pushClientAuth = self.pushAndroidServiceAuth elif platform == PushPlatform.APNS: pushClient = self.pushAppleService if self.pushSnsMode: platformApplicationArn = self.pushApplePlatformArn if self.pushGluuMode: pushClientAuth = self.pushAppleServiceAuth else: print "Super-Gluu-Push. Unsupported platform for ARN." return None deviceData = u2fDevice.getDeviceData() pushToken = deviceData.getPushToken() print "Super-Gluu-Push. Attempting to create target endpoint ARN for user: %s" % user.getUserId() if self.pushSnsMode: targetEndpointArn = pushSnsService.createPlatformArn(pushClient,platformApplicationArn,pushToken,user) else: customUserData = pushSnsService.getCustomUserData(user) registerDeviceResponse = pushClient.registerDevice(pushClientAuth, pushToken, customUserData) if registerDeviceResponse != None and registerDeviceResponse.getStatusCode() == 200: targetEndpointArn = registerDeviceResponse.getEndpointArn() if StringHelper.isEmpty(targetEndpointArn): print "Super-Gluu-Push. Failed to get endpoint ARN for user: '******'" % user.getUserId() return None printmsg = "Super-Gluu-Push. Create target endpoint ARN '%s' for user '%s'" print printmsg % (targetEndpointArn, user.getUserId()) # Store created endpoint ARN in device entry userInum = user.getAttribute("inum") u2fDeviceUpdate = deviceRegistrationService.findUserDeviceRegistration(userInum, u2fDevice.getId()) u2fDeviceUpdate.setDeviceNotificationConf('{"sns_endpoint_arn": "%s"}' % targetEndpointArn) deviceRegistrationService.updateDeviceRegistration(userInum,u2fDeviceUpdate) return targetEndpointArn