def initPushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize notification services" if not configurationAttributes.containsKey("credentials_file"): return False super_gluu_creds_file = configurationAttributes.get( "credentials_file").getValue2() # Load credentials from file f = open(super_gluu_creds_file, 'r') try: creds = json.loads(f.read()) except: print "Super-Gluu. Initialize notification services. Failed to load credentials from file:", super_gluu_creds_file return False finally: f.close() try: android_creds = creds["android"]["gcm"] ios_creads = creds["ios"]["apns"] except: print "Super-Gluu. Initialize notification services. Invalid credentials file '%s' format:" % super_gluu_creds_file return False self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu. Initialize notification services. Created Android notification service" if ios_creads["enabled"]: p12_file_path = ios_creads["p12_file_path"] p12_passowrd = ios_creads["p12_password"] try: stringEncrypter = StringEncrypter.defaultInstance() p12_passowrd = stringEncrypter.decrypt(p12_passowrd) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize notification services. Assuming that 'p12_passowrd' password in not encrypted" apnsServiceBuilder = APNS.newService().withCert( p12_file_path, p12_passowrd) if ios_creads["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination( ).build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination( ).build() print "Super-Gluu. Initialize notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled
def initNativePushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize native notification services" self.pushSnsMode = False creds = self.loadPushNotificationCreds(configurationAttributes) if creds == None: return False try: android_creds = creds["android"]["gcm"] ios_creads = creds["ios"]["apns"] except: print "Super-Gluu. Initialize native notification services. Invalid credentials file format" return False self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu. Initialize native notification services. Created Android notification service" if ios_creads["enabled"]: p12_file_path = ios_creads["p12_file_path"] p12_passowrd = ios_creads["p12_password"] try: encryptionService = CdiUtil.bean(EncryptionService) p12_passowrd = encryptionService.decrypt(p12_passowrd) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize native notification services. Assuming that 'p12_passowrd' password in not encrypted" apnsServiceBuilder = APNS.newService().withCert( p12_file_path, p12_passowrd) if ios_creads["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination( ).build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination( ).build() print "Super-Gluu. Initialize native notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled
def initNativePushNotifications(self, creds): print "Super-Gluu-Push. Native push notifications init ... " try: android_creds = creds["android"]["gcm"] ios_creds = creds["ios"]["apns"] except: print "Super-Gluu-Push. Invalid credentials format" return None self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu-Push. Created native Android notification service" if ios_creds["enabled"]: p12_file_path = ios_creds["p12_file_path"] p12_password = ios_creds["p12_password"] try: encryptionService = CdiUtil.bean(EncryptionService) p12_password = encryptionService.decrypt(p12_password) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'p12_password' is not encrypted" apnsServiceBuilder = APNS.newService().withCert( p12_file_path, p12_password) if ios_creds["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination( ).build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination( ).build() self.pushAppleServiceProduction = ios_creds["production"] print "Super-Gluu-Push. Created native iOS notification service" self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None
def initPushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize notification services" if not configurationAttributes.containsKey("credentials_file"): return False super_gluu_creds_file = configurationAttributes.get("credentials_file").getValue2() # Load credentials from file f = open(super_gluu_creds_file, 'r') try: creds = json.loads(f.read()) except: print "Super-Gluu. Initialize notification services. Failed to load credentials from file:", super_gluu_creds_file return False finally: f.close() try: android_creds = creds["android"]["gcm"] ios_creads = creds["ios"]["apns"] except: print "Super-Gluu. Initialize notification services. Invalid credentials file '%s' format:" % super_gluu_creds_file return False self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu. Initialize notification services. Created Android notification service" if ios_creads["enabled"]: p12_file_path = ios_creads["p12_file_path"] p12_passowrd = ios_creads["p12_password"] try: stringEncrypter = StringEncrypter.defaultInstance() p12_passowrd = stringEncrypter.decrypt(p12_passowrd) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize notification services. Assuming that 'p12_passowrd' password in not encrypted" apnsServiceBuilder = APNS.newService().withCert(p12_file_path, p12_passowrd) if ios_creads["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination().build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build() print "Super-Gluu. Initialize notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled
def initNativePushNotifications(self, creds): print "Super-Gluu-Push. Native push notifications init ... " try: android_creds = creds["android"]["gcm"] ios_creds = creds["ios"]["apns"] except: print "Super-Gluu-Push. Invalid credentials format" return None self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu-Push. Created native Android notification service" if ios_creds["enabled"]: p12_file_path = ios_creds["p12_file_path"] p12_password = ios_creds["p12_password"] try: encryptionService = CdiUtil.bean(EncryptionService) p12_password = encryptionService.decrypt(p12_password) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'p12_password' is not encrypted" apnsServiceBuilder = APNS.newService().withCert(p12_file_path,p12_password) if ios_creds["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination().build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build() self.pushAppleServiceProduction = ios_creds["production"] print "Super-Gluu-Push. Created native iOS notification service" self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None
class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print "Super-Gluu. Initialization" if not configurationAttributes.containsKey("authentication_mode"): print "Super-Gluu. Initialization. Property authentication_mode is mandatory" return False self.registrationUri = None if configurationAttributes.containsKey("registration_uri"): self.registrationUri = configurationAttributes.get("registration_uri").getValue2() authentication_mode = configurationAttributes.get("authentication_mode").getValue2() if StringHelper.isEmpty(authentication_mode): print "Super-Gluu. Initialization. Failed to determine authentication_mode. authentication_mode configuration parameter is empty" return False self.oneStep = StringHelper.equalsIgnoreCase(authentication_mode, "one_step") self.twoStep = StringHelper.equalsIgnoreCase(authentication_mode, "two_step") if not (self.oneStep or self.twoStep): print "Super-Gluu. Initialization. Valid authentication_mode values are one_step and two_step" return False self.enabledPushNotifications = self.initPushNotificationService(configurationAttributes) self.customLabel = None if configurationAttributes.containsKey("label"): self.customLabel = configurationAttributes.get("label").getValue2() self.customQrOptions = {} if configurationAttributes.containsKey("qr_options"): self.customQrOptions = configurationAttributes.get("qr_options").getValue2() print "Super-Gluu. Initialized successfully. oneStep: '%s', twoStep: '%s', pushNotifications: '%s', customLabel: '%s'" % (self.oneStep, self.twoStep, self.enabledPushNotifications, self.customLabel) return True def destroy(self, configurationAttributes): print "Super-Gluu. Destroy" print "Super-Gluu. Destroyed successfully" return True def getApiVersion(self): return 1 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): credentials = Identity.instance().getCredentials() user_name = credentials.getUsername() context = Contexts.getEventContext() session_attributes = context.get("sessionAttributes") client_redirect_uri = self.getClientRedirecUri(session_attributes) if client_redirect_uri == None: print "Super-Gluu. Authenticate. redirect_uri is not set" return False self.setEventContextParameters(context) userService = UserService.instance() deviceRegistrationService = DeviceRegistrationService.instance() if step == 1: print "Super-Gluu. Authenticate for step 1" if self.oneStep: session_device_status = self.getSessionDeviceStatus(session_attributes, user_name) if session_device_status == None: return u2f_device_id = session_device_status['device_id'] validation_result = self.validateSessionDeviceStatus(client_redirect_uri, session_device_status) if validation_result: print "Super-Gluu. Authenticate for step 1. User successfully authenticated with u2f_device '%s'" % u2f_device_id else: return False if not session_device_status['one_step']: print "Super-Gluu. Authenticate for step 1. u2f_device '%s' is not one step device" % u2f_device_id return False # There are two steps only in enrollment mode if session_device_status['enroll']: return validation_result context.set("super_gluu_count_login_steps", 1) user_inum = session_device_status['user_inum'] u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id, "oxId") if u2f_device == None: print "Super-Gluu. Authenticate for step 1. Failed to load u2f_device '%s'" % u2f_device_id return False logged_in = userService.authenticate(user_name) if not logged_in: print "Super-Gluu. Authenticate for step 1. Failed to authenticate user '%s'" % user_name return False print "Super-Gluu. Authenticate for step 1. User '%s' successfully authenticated with u2f_device '%s'" % (user_name, u2f_device_id) return True elif self.twoStep: authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False auth_method = 'authenticate' enrollment_mode = ServerUtil.getFirstValue(requestParameters, "loginForm:registerButton") if StringHelper.isNotEmpty(enrollment_mode): auth_method = 'enroll' if auth_method == 'authenticate': user_inum = userService.getUserInum(authenticated_user) u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, client_redirect_uri, "oxId") if u2f_devices_list.size() == 0: auth_method = 'enroll' print "Super-Gluu. Authenticate for step 1. There is no U2F '%s' user devices associated with application '%s'. Changing auth_method to '%s'" % (user_name, client_redirect_uri, auth_method) print "Super-Gluu. Authenticate for step 1. auth_method: '%s'" % auth_method context.set("super_gluu_auth_method", auth_method) return True return False elif step == 2: print "Super-Gluu. Authenticate for step 2" session_attributes = context.get("sessionAttributes") session_device_status = self.getSessionDeviceStatus(session_attributes, user_name) if session_device_status == None: return False u2f_device_id = session_device_status['device_id'] # There are two steps only in enrollment mode if self.oneStep and session_device_status['enroll']: authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False user_inum = userService.getUserInum(authenticated_user) attach_result = deviceRegistrationService.attachUserDeviceRegistration(user_inum, u2f_device_id) print "Super-Gluu. Authenticate for step 2. Result after attaching u2f_device '%s' to user '%s': '%s'" % (u2f_device_id, user_name, attach_result) return attach_result elif self.twoStep: if user_name == None: print "Super-Gluu. Authenticate for step 2. Failed to determine user name" return False validation_result = self.validateSessionDeviceStatus(client_redirect_uri, session_device_status, user_name) if validation_result: print "Super-Gluu. Authenticate for step 2. User '%s' successfully authenticated with u2f_device '%s'" % (user_name, u2f_device_id) else: return False super_gluu_request = json.loads(session_device_status['super_gluu_request']) auth_method = super_gluu_request['method'] if auth_method in ['enroll', 'authenticate']: return validation_result print "Super-Gluu. Authenticate for step 2. U2F auth_method is invalid" return False else: return False def prepareForStep(self, configurationAttributes, requestParameters, step): context = Contexts.getEventContext() session_attributes = context.get("sessionAttributes") client_redirect_uri = self.getClientRedirecUri(session_attributes) if client_redirect_uri == None: print "Super-Gluu. Prepare for step. redirect_uri is not set" return False self.setEventContextParameters(context) if step == 1: print "Super-Gluu. Prepare for step 1" if self.oneStep: session_state = SessionStateService.instance().getSessionStateFromCookie() if StringHelper.isEmpty(session_state): print "Super-Gluu. Prepare for step 2. Failed to determine session_state" return False issuer = ConfigurationFactory.instance().getConfiguration().getIssuer() super_gluu_request_dictionary = {'app': client_redirect_uri, 'issuer': issuer, 'state': session_state, 'created': datetime.datetime.now().isoformat()} self.addGeolocationData(session_attributes, super_gluu_request_dictionary) super_gluu_request = json.dumps(super_gluu_request_dictionary, separators=(',',':')) print "Super-Gluu. Prepare for step 1. Prepared super_gluu_request:", super_gluu_request context.set("super_gluu_request", super_gluu_request) # elif self.twoStep: # context.set("display_register_action", True) return True elif step == 2: print "Super-Gluu. Prepare for step 2" if self.oneStep: return True authenticationService = AuthenticationService.instance() user = authenticationService.getAuthenticatedUser() if user == None: print "Super-Gluu. Prepare for step 2. Failed to determine user name" return False if session_attributes.containsKey("super_gluu_request"): print "Super-Gluu. Prepare for step 2. Request was generated already" return True session_state = SessionStateService.instance().getSessionStateFromCookie() if StringHelper.isEmpty(session_state): print "Super-Gluu. Prepare for step 2. Failed to determine session_state" return False auth_method = session_attributes.get("super_gluu_auth_method") if StringHelper.isEmpty(auth_method): print "Super-Gluu. Prepare for step 2. Failed to determine auth_method" return False print "Super-Gluu. Prepare for step 2. auth_method: '%s'" % auth_method issuer = ConfigurationFactory.instance().getConfiguration().getIssuer() super_gluu_request_dictionary = {'username': user.getUserId(), 'app': client_redirect_uri, 'issuer': issuer, 'method': auth_method, 'state': session_state, 'created': datetime.datetime.now().isoformat()} self.addGeolocationData(session_attributes, super_gluu_request_dictionary) super_gluu_request = json.dumps(super_gluu_request_dictionary, separators=(',',':')) print "Super-Gluu. Prepare for step 2. Prepared super_gluu_request:", super_gluu_request context.set("super_gluu_request", super_gluu_request) if auth_method in ['authenticate']: self.sendPushNotification(client_redirect_uri, user, super_gluu_request) return True else: return False def getExtraParametersForStep(self, configurationAttributes, step): if step == 1: if self.oneStep: return Arrays.asList("super_gluu_request") elif self.twoStep: return Arrays.asList("display_register_action") elif step == 2: return Arrays.asList("super_gluu_auth_method", "super_gluu_request") return None def getCountAuthenticationSteps(self, configurationAttributes): context = Contexts.getEventContext() if context.isSet("super_gluu_count_login_steps"): return context.get("super_gluu_count_login_steps") else: return 2 def getPageForStep(self, configurationAttributes, step): if step == 1: if self.oneStep: return "/auth/super-gluu/login.xhtml" elif step == 2: if self.oneStep: return "/login.xhtml" else: return "/auth/super-gluu/login.xhtml" return "" def logout(self, configurationAttributes, requestParameters): return True def processBasicAuthentication(self, credentials): userService = UserService.instance() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): logged_in = userService.authenticate(user_name, user_password) if not logged_in: return None find_user_by_uid = userService.getUser(user_name) if find_user_by_uid == None: print "Super-Gluu. Process basic authentication. Failed to find user '%s'" % user_name return None return find_user_by_uid def validateSessionDeviceStatus(self, client_redirect_uri, session_device_status, user_name = None): userService = UserService.instance() deviceRegistrationService = DeviceRegistrationService.instance() u2f_device_id = session_device_status['device_id'] u2f_device = None if session_device_status['enroll'] and session_device_status['one_step']: u2f_device = deviceRegistrationService.findOneStepUserDeviceRegistration(u2f_device_id) if u2f_device == None: print "Super-Gluu. Validate session device status. There is no one step u2f_device '%s'" % u2f_device_id return False else: # Validate if user has specified device_id enrollment user_inum = userService.getUserInum(user_name) if session_device_status['one_step']: user_inum = session_device_status['user_inum'] u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id) if u2f_device == None: print "Super-Gluu. Validate session device status. There is no u2f_device '%s' associated with user '%s'" % (u2f_device_id, user_inum) return False if not StringHelper.equalsIgnoreCase(client_redirect_uri, u2f_device.application): print "Super-Gluu. Validate session device status. u2f_device '%s' associated with other application '%s'" % (u2f_device_id, u2f_device.application) return False return True def getSessionDeviceStatus(self, session_attributes, user_name): print "Super-Gluu. Get session device status" if not session_attributes.containsKey("super_gluu_request"): print "Super-Gluu. Get session device status. There is no Super-Gluu request in session attributes" return None # Check session state extended if not session_attributes.containsKey("session_custom_state"): print "Super-Gluu. Get session device status. There is no session_custom_state in session attributes" return None session_custom_state = session_attributes.get("session_custom_state") if not StringHelper.equalsIgnoreCase("approved", session_custom_state): print "Super-Gluu. Get session device status. User '%s' not approve or not pass U2F authentication. session_custom_state: '%s'" % (user_name, session_custom_state) return None # Try to find device_id in session attribute if not session_attributes.containsKey("oxpush2_u2f_device_id"): print "Super-Gluu. Get session device status. There is no u2f_device associated with this request" return None # Try to find user_inum in session attribute if not session_attributes.containsKey("oxpush2_u2f_device_user_inum"): print "Super-Gluu. Get session device status. There is no user_inum associated with this request" return None enroll = False if session_attributes.containsKey("oxpush2_u2f_device_enroll"): enroll = StringHelper.equalsIgnoreCase("true", session_attributes.get("oxpush2_u2f_device_enroll")) one_step = False if session_attributes.containsKey("oxpush2_u2f_device_one_step"): one_step = StringHelper.equalsIgnoreCase("true", session_attributes.get("oxpush2_u2f_device_one_step")) super_gluu_request = session_attributes.get("super_gluu_request") u2f_device_id = session_attributes.get("oxpush2_u2f_device_id") user_inum = session_attributes.get("oxpush2_u2f_device_user_inum") session_device_status = {"super_gluu_request": super_gluu_request, "device_id": u2f_device_id, "user_inum" : user_inum, "enroll" : enroll, "one_step" : one_step} print "Super-Gluu. Get session device status. session_device_status: '%s'" % (session_device_status) return session_device_status def initPushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize notification services" if not configurationAttributes.containsKey("credentials_file"): return False super_gluu_creds_file = configurationAttributes.get("credentials_file").getValue2() # Load credentials from file f = open(super_gluu_creds_file, 'r') try: creds = json.loads(f.read()) except: print "Super-Gluu. Initialize notification services. Failed to load credentials from file:", super_gluu_creds_file return False finally: f.close() try: android_creds = creds["android"]["gcm"] ios_creads = creds["ios"]["apns"] except: print "Super-Gluu. Initialize notification services. Invalid credentials file '%s' format:" % super_gluu_creds_file return False self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu. Initialize notification services. Created Android notification service" if ios_creads["enabled"]: p12_file_path = ios_creads["p12_file_path"] p12_passowrd = ios_creads["p12_password"] try: stringEncrypter = StringEncrypter.defaultInstance() p12_passowrd = stringEncrypter.decrypt(p12_passowrd) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize notification services. Assuming that 'p12_passowrd' password in not encrypted" apnsServiceBuilder = APNS.newService().withCert(p12_file_path, p12_passowrd) if ios_creads["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination().build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build() print "Super-Gluu. Initialize notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled def sendPushNotification(self, client_redirect_uri, user, super_gluu_request): if not self.enabledPushNotifications: return user_name = user.getUserId() print "Super-Gluu. Send push notification. Loading user '%s' devices" % user_name send_notification = False send_notification_result = True userService = UserService.instance() deviceRegistrationService = DeviceRegistrationService.instance() user_inum = userService.getUserInum(user_name) u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, client_redirect_uri, "oxId", "oxDeviceData") if u2f_devices_list.size() > 0: for u2f_device in u2f_devices_list: device_data = u2f_device.getDeviceData() # Device data which Super-Gluu gets during enrollment if device_data == None: continue platform = device_data.getPlatform() push_token = device_data.getPushToken() debug = False if StringHelper.equalsIgnoreCase(platform, "ios") and StringHelper.isNotEmpty(push_token): # Sending notification to iOS user's device if self.pushAppleService == None: print "Super-Gluu. Send push notification. Apple push notification service is not enabled" else: send_notification = True title = "Super-Gluu" message = "Super-Gluu login request to: %s" % client_redirect_uri additional_fields = { "request" : super_gluu_request } msgBuilder = APNS.newPayload().alertBody(message).alertTitle(title).sound("default") msgBuilder.category('ACTIONABLE').badge(0) msgBuilder.forNewsstand() msgBuilder.customFields(additional_fields) push_message = msgBuilder.build() send_notification_result = self.pushAppleService.push(push_token, push_message) if debug: print "Super-Gluu. Send iOS push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) if StringHelper.equalsIgnoreCase(platform, "android") and StringHelper.isNotEmpty(push_token): # Sending notification to Android user's device if self.pushAndroidService == None: print "Super-Gluu. Send push notification. Android push notification service is not enabled" else: send_notification = True title = "Super-Gluu" msgBuilder = Message.Builder().addData("message", super_gluu_request).addData("title", title).collapseKey("single").contentAvailable(True) push_message = msgBuilder.build() send_notification_result = self.pushAndroidService.send(push_message, push_token, 3) if debug: print "Super-Gluu. Send Android push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) print "Super-Gluu. Send push notification. send_notification: '%s', send_notification_result: '%s'" % (send_notification, send_notification_result) def getClientRedirecUri(self, session_attributes): if not session_attributes.containsKey("redirect_uri"): return None return session_attributes.get("redirect_uri") def setEventContextParameters(self, context): if self.registrationUri != None: context.set("external_registration_uri", self.registrationUri) if self.customLabel != None: context.set("super_gluu_label", self.customLabel) context.set("super_gluu_qr_options", self.customQrOptions) def addGeolocationData(self, session_attributes, super_gluu_request_dictionary): if session_attributes.containsKey("remote_ip"): remote_ip = session_attributes.get("remote_ip") if StringHelper.isNotEmpty(remote_ip): print "Super-Gluu. Prepare for step 2. Adding req_ip and req_loc to super_gluu_request" super_gluu_request_dictionary['req_ip'] = remote_ip remote_loc_dic = self.determineGeolocationData(remote_ip) if remote_loc_dic == None: print "Super-Gluu. Prepare for step 2. Failed to determine remote location by remote IP '%s'" % remote_ip return remote_loc = "%s, %s, %s" % ( remote_loc_dic['country'], remote_loc_dic['regionName'], remote_loc_dic['city'] ) remote_loc_encoded = urllib.quote(remote_loc) super_gluu_request_dictionary['req_loc'] = remote_loc_encoded def determineGeolocationData(self, remote_ip): print "Super-Gluu. Determine remote location. remote_ip: '%s'" % remote_ip httpService = HttpService.instance() http_client = httpService.getHttpsClient() http_client_params = http_client.getParams() http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000) geolocation_service_url = "http://ip-api.com/json/%s?fields=49177" % 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 "Super-Gluu. Determine remote location. Exception: ", sys.exc_info()[1] return None try: if not httpService.isResponseStastusCodeOk(http_response): print "Super-Gluu. Determine remote location. Get invalid response from validation server: ", str(http_response.getStatusLine().getStatusCode()) httpService.consume(http_response) return None response_bytes = httpService.getResponseContent(http_response) response_string = httpService.convertEntityToString(response_bytes) httpService.consume(http_response) finally: http_service_response.closeConnection() if response_string == None: print "Super-Gluu. Determine remote location. Get empty response from location server" return None response = json.loads(response_string) if not StringHelper.equalsIgnoreCase(response['status'], "success"): print "Super-Gluu. Determine remote location. Get response with status: '%s'" % response['status'] return None return response
class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print "oxPush2. Initialization" if not (configurationAttributes.containsKey("application_id") and configurationAttributes.containsKey("authentication_mode")): print "oxPush2. Initialization. Properties application_id and authentication_mode are mandatory" return False self.application_id = configurationAttributes.get("application_id").getValue2() if StringHelper.isEmpty(self.application_id): print "oxPush2. Initialization. Failed to determine application_id. application_id configuration parameter is empty" return False authentication_mode = configurationAttributes.get("authentication_mode").getValue2() if StringHelper.isEmpty(authentication_mode): print "oxPush2. Initialization. Failed to determine authentication_mode. authentication_mode configuration parameter is empty" return False self.oneStep = StringHelper.equalsIgnoreCase(authentication_mode, "one_step") self.twoStep = StringHelper.equalsIgnoreCase(authentication_mode, "two_step") if not (self.oneStep or self.twoStep): print "oxPush2. Initialization. Valid authentication_mode values are one_step and two_step" return False self.enabledPushNotifications = self.initPushNotificationService(configurationAttributes) print "oxPush2. Initialized successfully. oneStep: '%s', twoStep: '%s', pushNotifications: '%s'" % (self.oneStep, self.twoStep, self.enabledPushNotifications) return True def destroy(self, configurationAttributes): print "oxPush2. Destroy" print "oxPush2. Destroyed successfully" return True def getApiVersion(self): return 1 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): credentials = Identity.instance().getCredentials() user_name = credentials.getUsername() context = Contexts.getEventContext() userService = UserService.instance() deviceRegistrationService = DeviceRegistrationService.instance() if (step == 1): print "oxPush2. Authenticate for step 1" if self.oneStep: session_attributes = context.get("sessionAttributes") session_device_status = self.getSessionDeviceStatus(session_attributes); if session_device_status == None: return u2f_device_id = session_device_status['device_id'] validation_result = self.validateSessionDeviceStatus(session_device_status) if validation_result: print "oxPush2. Authenticate for step 1. User successfully authenticated with u2f_device '%s'" % u2f_device_id else: return False if not session_device_status['one_step']: print "oxPush2. Authenticate for step 1. u2f_device '%s' is not one step device" % u2f_device_id return False # There are two steps only in enrollment mode if session_device_status['enroll']: return validation_result context.set("oxpush2_count_login_steps", 1) user_inum = session_device_status['user_inum'] u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id, "oxId") if u2f_device == None: print "oxPush2. Authenticate for step 1. Failed to load u2f_device '%s'" % u2f_device_id return False logged_in = userService.authenticate(user_name) if (not logged_in): print "oxPush2. Authenticate for step 1. Failed to authenticate user '%s'" % user_name return False print "oxPush2. Authenticate for step 1. User '%s' successfully authenticated with u2f_device '%s'" % (user_name, u2f_device_id) return True; elif self.twoStep: authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False auth_method = 'authenticate' enrollment_mode = ServerUtil.getFirstValue(requestParameters, "loginForm:registerButton") if StringHelper.isNotEmpty(enrollment_mode): auth_method = 'enroll' if (auth_method == 'authenticate'): user_inum = userService.getUserInum(authenticated_user) u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, self.application_id, "oxId") if (u2f_devices_list.size() == 0): auth_method = 'enroll' print "oxPush2. Authenticate for step 1. There is no U2F '%s' user devices associated with application '%s'. Changing auth_method to '%s'" % (user_name, self.application_id, auth_method) print "oxPush2. Authenticate for step 1. auth_method: '%s'" % auth_method context.set("oxpush2_auth_method", auth_method) return True return False elif (step == 2): print "oxPush2. Authenticate for step 2" session_attributes = context.get("sessionAttributes") session_device_status = self.getSessionDeviceStatus(session_attributes); if session_device_status == None: return False u2f_device_id = session_device_status['device_id'] # There are two steps only in enrollment mode if self.oneStep and session_device_status['enroll']: authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False user_inum = userService.getUserInum(authenticated_user) attach_result = deviceRegistrationService.attachUserDeviceRegistration(user_inum, u2f_device_id) print "oxPush2. Authenticate for step 2. Result after attaching u2f_device '%s' to user '%s': '%s'" % (u2f_device_id, user_name, attach_result) return attach_result elif self.twoStep: if (user_name == None): print "oxPush2. Authenticate for step 2. Failed to determine user name" return False validation_result = self.validateSessionDeviceStatus(session_device_status, user_name) if validation_result: print "oxPush2. Authenticate for step 2. User '%s' successfully authenticated with u2f_device '%s'" % (user_name, u2f_device_id) else: return False oxpush2_request = json.loads(session_device_status['oxpush2_request']) auth_method = oxpush2_request['method'] if auth_method in ['enroll', 'authenticate']: return validation_result print "oxPush2. Authenticate for step 2. U2F auth_method is invalid" return False else: return False def prepareForStep(self, configurationAttributes, requestParameters, step): context = Contexts.getEventContext() if step == 1: print "oxPush2. Prepare for step 1" if self.oneStep: session_state = SessionStateService.instance().getSessionStateFromCookie() if StringHelper.isEmpty(session_state): print "oxPush2. Prepare for step 2. Failed to determine session_state" return False issuer = ConfigurationFactory.instance().getConfiguration().getIssuer() oxpush2_request = json.dumps({'app': self.application_id, 'issuer': issuer, 'state': session_state, 'created': datetime.datetime.now().isoformat()}, separators=(',',':')) print "oxPush2. Prepare for step 1. Prepared oxpush2_request:", oxpush2_request context.set("oxpush2_request", oxpush2_request) elif self.twoStep: context.set("display_register_action", True) return True elif step == 2: print "oxPush2. Prepare for step 2" if self.oneStep: return True credentials = Identity.instance().getCredentials() user = credentials.getUser() if user == None: print "oxPush2. Prepare for step 2. Failed to determine user name" return False session_attributes = context.get("sessionAttributes") if session_attributes.containsKey("oxpush2_request"): print "oxPush2. Prepare for step 2. Request was generated already" return True session_state = SessionStateService.instance().getSessionStateFromCookie() if StringHelper.isEmpty(session_state): print "oxPush2. Prepare for step 2. Failed to determine session_state" return False auth_method = session_attributes.get("oxpush2_auth_method") if StringHelper.isEmpty(auth_method): print "oxPush2. Prepare for step 2. Failed to determine auth_method" return False print "oxPush2. Prepare for step 2. auth_method: '%s'" % auth_method issuer = ConfigurationFactory.instance().getConfiguration().getIssuer() oxpush2_request = json.dumps({'username': user.getUserId(), 'app': self.application_id, 'issuer': issuer, 'method': auth_method, 'state': session_state, 'created': datetime.datetime.now().isoformat()}, separators=(',',':')) print "oxPush2. Prepare for step 2. Prepared oxpush2_request:", oxpush2_request context.set("oxpush2_request", oxpush2_request) if auth_method in ['authenticate']: self.sendPushNotification(user, oxpush2_request) return True else: return False def getExtraParametersForStep(self, configurationAttributes, step): if (step == 1): if self.oneStep: return Arrays.asList("oxpush2_request") elif self.twoStep: return Arrays.asList("display_register_action") elif (step == 2): return Arrays.asList("oxpush2_auth_method", "oxpush2_request") return None def getCountAuthenticationSteps(self, configurationAttributes): context = Contexts.getEventContext() if (context.isSet("oxpush2_count_login_steps")): return context.get("oxpush2_count_login_steps") else: return 2 def getPageForStep(self, configurationAttributes, step): if (step == 1): if self.oneStep: return "/auth/oxpush2/login.xhtml" elif (step == 2): if self.oneStep: return "/login.xhtml" else: return "/auth/oxpush2/login.xhtml" return "" def logout(self, configurationAttributes, requestParameters): return True def processBasicAuthentication(self, credentials): userService = UserService.instance() user_name = credentials.getUsername() user_password = credentials.getPassword() logged_in = False if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): logged_in = userService.authenticate(user_name, user_password) if (not logged_in): return None find_user_by_uid = userService.getUser(user_name) if (find_user_by_uid == None): print "oxPush. Process basic authentication. Failed to find user '%s'" % user_name return None return find_user_by_uid def validateSessionDeviceStatus(self, session_device_status, user_name = None): userService = UserService.instance() deviceRegistrationService = DeviceRegistrationService.instance() u2f_device_id = session_device_status['device_id'] u2f_device = None if session_device_status['enroll'] and session_device_status['one_step']: u2f_device = deviceRegistrationService.findOneStepUserDeviceRegistration(u2f_device_id) if (u2f_device == None): print "oxPush2. Validate session device status. There is no one step u2f_device '%s'" % u2f_device_id return False else: # Validate if user has specified device_id enrollment user_inum = userService.getUserInum(user_name) if session_device_status['one_step']: user_inum = session_device_status['user_inum'] u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id) if u2f_device == None: print "oxPush2. Validate session device status. There is no u2f_device '%s' associated with user '%s'" % (u2f_device_id, user_inum) return False if not StringHelper.equalsIgnoreCase(self.application_id, u2f_device.application): print "oxPush2. Validate session device status. u2f_device '%s' associated with other application '%s'" % (u2f_device_id, u2f_device.application) return False return True def getSessionDeviceStatus(self, session_attributes): print "oxPush2. Get session device status" if not session_attributes.containsKey("oxpush2_request"): print "oxPush2. Get session device status. There is no oxPush2 request in session attributes" return None # Check session state extended if not session_attributes.containsKey("session_custom_state"): print "oxPush2. Get session device status. There is no session_custom_state in session attributes" return None session_custom_state = session_attributes.get("session_custom_state") if not StringHelper.equalsIgnoreCase("approved", session_custom_state): print "oxPush2. Get session device status. User '%s' not approve or pass U2F authentication. session_custom_state: '%s'" % (user_name, session_custom_state) return None # Try to find device_id in session attribute if not session_attributes.containsKey("oxpush2_u2f_device_id"): print "oxPush2. Get session device status. There is no u2f_device associated with this request" return None # Try to find user_inum in session attribute if not session_attributes.containsKey("oxpush2_u2f_device_user_inum"): print "oxPush2. Get session device status. There is no user_inum associated with this request" return None enroll = False if session_attributes.containsKey("oxpush2_u2f_device_enroll"): enroll = StringHelper.equalsIgnoreCase("true", session_attributes.get("oxpush2_u2f_device_enroll")) one_step = False if session_attributes.containsKey("oxpush2_u2f_device_one_step"): one_step = StringHelper.equalsIgnoreCase("true", session_attributes.get("oxpush2_u2f_device_one_step")) oxpush2_request = session_attributes.get("oxpush2_request") u2f_device_id = session_attributes.get("oxpush2_u2f_device_id") user_inum = session_attributes.get("oxpush2_u2f_device_user_inum") session_device_status = {"oxpush2_request": oxpush2_request, "device_id": u2f_device_id, "user_inum" : user_inum, "enroll" : enroll, "one_step" : one_step} print "oxPush2. Get session device status. session_device_status: '%s'" % (session_device_status) return session_device_status def initPushNotificationService(self, configurationAttributes): print "oxPush2. Initialize notification services" if not configurationAttributes.containsKey("credentials_file"): return False oxpush2_creds_file = configurationAttributes.get("credentials_file").getValue2() # Load credentials from file f = open(oxpush2_creds_file, 'r') try: creds = json.loads(f.read()) except: print "oxPush2. Initialize notification services. Failed to load credentials from file:", oxpush2_creds_file return False finally: f.close() try: android_creds = creds["android"]["gcm"] ios_creads = creds["ios"]["apns"] except: print "oxPush2. Initialize notification services. Invalid credentials file '%s' format:" % oxpush2_creds_file return False self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "oxPush2. Initialize notification services. Created Android notification service" if ios_creads["enabled"]: p12_file_path = ios_creads["p12_file_path"] p12_passowrd = ios_creads["p12_password"] try: stringEncrypter = StringEncrypter.defaultInstance() p12_passowrd = stringEncrypter.decrypt(p12_passowrd) except: # Ignore exception. Password is not encrypted print "oxPush2. Initialize notification services. Assuming that 'p12_passowrd' password in not encrypted" apnsServiceBuilder = APNS.newService().withCert(p12_file_path, p12_passowrd) if ios_creads["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination().build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build() print "oxPush2. Initialize notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled def sendPushNotification(self, user, oxpush2_request): if not self.enabledPushNotifications: return user_name = user.getUserId() print "oxPush2. Send push notification. Loading user '%s' devices" % user_name send_notification = False send_notification_result = True userService = UserService.instance() deviceRegistrationService = DeviceRegistrationService.instance() user_inum = userService.getUserInum(user_name) u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, self.application_id, "oxId", "oxDeviceData") if u2f_devices_list.size() > 0: for u2f_device in u2f_devices_list: device_data = u2f_device.getDeviceData() # Device data which oxPush2 gets during enrollment if device_data == None: continue platform = device_data.getPlatform() push_token = device_data.getPushToken() debug = False if StringHelper.equalsIgnoreCase(platform, "ios") and StringHelper.isNotEmpty(push_token): # Sending notification to iOS user's device if (self.pushAppleService == None): print "oxPush2. Send push notification. Apple push notification service is not enabled" else: send_notification = True title = "oxPush2" message = "oxPush2 login request to: %s" % self.application_id additional_fields = { "request" : oxpush2_request } msgBuilder = APNS.newPayload().alertBody(message).alertTitle(title).sound("default") msgBuilder.category('ACTIONABLE').badge(0) msgBuilder.customFields(additional_fields) send_notification_result = self.pushAppleService.push(push_token, msgBuilder.build()) if debug: print "oxPush2. Send push notification. token: '%s', send_notification_result: '%s'" % (push_token, send_notification_result) if StringHelper.equalsIgnoreCase(platform, "android") and StringHelper.isNotEmpty(push_token): # Sending notification to Android user's device if (self.pushAndroidService == None): print "oxPush2. Send push notification. Android push notification service is not enabled" else: send_notification = True title = "oxPush2" msgBuilder = Message.Builder().addData("message", oxpush2_request).addData("title", title).collapseKey("single"); send_notification_result = self.pushAndroidService.send(msgBuilder.build(), push_token, 3) if debug: print "oxPush2. Send push notification. token: '%s', send_notification_result: '%s'" % (push_token, send_notification_result) print "oxPush2. Send push notification. send_notification: '%s', send_notification_result: '%s'" % (send_notification, send_notification_result)
class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def init(self, configurationAttributes): print "Super-Gluu. Initialization" if not configurationAttributes.containsKey("authentication_mode"): print "Super-Gluu. Initialization. Property authentication_mode is mandatory" return False self.registrationUri = None if configurationAttributes.containsKey("registration_uri"): self.registrationUri = configurationAttributes.get("registration_uri").getValue2() authentication_mode = configurationAttributes.get("authentication_mode").getValue2() if StringHelper.isEmpty(authentication_mode): print "Super-Gluu. Initialization. Failed to determine authentication_mode. authentication_mode configuration parameter is empty" return False self.oneStep = StringHelper.equalsIgnoreCase(authentication_mode, "one_step") self.twoStep = StringHelper.equalsIgnoreCase(authentication_mode, "two_step") if not (self.oneStep or self.twoStep): print "Super-Gluu. Initialization. Valid authentication_mode values are one_step and two_step" return False self.enabledPushNotifications = self.initPushNotificationService(configurationAttributes) self.androidUrl = None if configurationAttributes.containsKey("supergluu_android_download_url"): self.androidUrl = configurationAttributes.get("supergluu_android_download_url").getValue2() self.IOSUrl = None if configurationAttributes.containsKey("supergluu_ios_download_url"): self.IOSUrl = configurationAttributes.get("supergluu_ios_download_url").getValue2() self.customLabel = None if configurationAttributes.containsKey("label"): self.customLabel = configurationAttributes.get("label").getValue2() self.customQrOptions = {} if configurationAttributes.containsKey("qr_options"): self.customQrOptions = configurationAttributes.get("qr_options").getValue2() self.use_super_gluu_group = False if configurationAttributes.containsKey("super_gluu_group"): self.super_gluu_group = configurationAttributes.get("super_gluu_group").getValue2() self.use_super_gluu_group = True print "Super-Gluu. Initialization. Using super_gluu only if user belong to group: %s" % self.super_gluu_group self.use_audit_group = False if configurationAttributes.containsKey("audit_group"): self.audit_group = configurationAttributes.get("audit_group").getValue2() if (not configurationAttributes.containsKey("audit_group_email")): print "Super-Gluu. Initialization. Property audit_group_email is not specified" return False self.audit_email = configurationAttributes.get("audit_group_email").getValue2() self.use_audit_group = True print "Super-Gluu. Initialization. Using audit group: %s" % self.audit_group if self.use_super_gluu_group or self.use_audit_group: if not configurationAttributes.containsKey("audit_attribute"): print "Super-Gluu. Initialization. Property audit_attribute is not specified" return False else: self.audit_attribute = configurationAttributes.get("audit_attribute").getValue2() print "Super-Gluu. Initialized successfully. oneStep: '%s', twoStep: '%s', pushNotifications: '%s', customLabel: '%s'" % (self.oneStep, self.twoStep, self.enabledPushNotifications, self.customLabel) return True def destroy(self, configurationAttributes): print "Super-Gluu. Destroy" self.pushAndroidService = None self.pushAppleService = None print "Super-Gluu. Destroyed successfully" return True def getApiVersion(self): return 2 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticate(self, configurationAttributes, requestParameters, step): authenticationService = CdiUtil.bean(AuthenticationService) identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() session_attributes = identity.getSessionId().getSessionAttributes() client_redirect_uri = self.getClientRedirecUri(session_attributes) if client_redirect_uri == None: print "Super-Gluu. Authenticate. redirect_uri is not set" return False self.setRequestScopedParameters(identity, step) # Validate form result code and initialize QR code regeneration if needed (retry_current_step = True) identity.setWorkingParameter("retry_current_step", False) form_auth_result = ServerUtil.getFirstValue(requestParameters, "auth_result") if StringHelper.isNotEmpty(form_auth_result): print "Super-Gluu. Authenticate for step %s. Get auth_result: '%s'" % (step, form_auth_result) if form_auth_result in ['error']: return False if form_auth_result in ['timeout']: if ((step == 1) and self.oneStep) or ((step == 2) and self.twoStep): print "Super-Gluu. Authenticate for step %s. Reinitializing current step" % step identity.setWorkingParameter("retry_current_step", True) return False userService = CdiUtil.bean(UserService) deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) if step == 1: print "Super-Gluu. Authenticate for step 1" user_name = credentials.getUsername() if self.oneStep: session_device_status = self.getSessionDeviceStatus(session_attributes, user_name) if session_device_status == None: return False u2f_device_id = session_device_status['device_id'] validation_result = self.validateSessionDeviceStatus(client_redirect_uri, session_device_status) if validation_result: print "Super-Gluu. Authenticate for step 1. User successfully authenticated with u2f_device '%s'" % u2f_device_id else: return False if not session_device_status['one_step']: print "Super-Gluu. Authenticate for step 1. u2f_device '%s' is not one step device" % u2f_device_id return False # There are two steps only in enrollment mode if session_device_status['enroll']: return validation_result identity.setWorkingParameter("super_gluu_count_login_steps", 1) user_inum = session_device_status['user_inum'] u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id, "oxId") if u2f_device == None: print "Super-Gluu. Authenticate for step 1. Failed to load u2f_device '%s'" % u2f_device_id return False logged_in = authenticationService.authenticate(user_name) if not logged_in: print "Super-Gluu. Authenticate for step 1. Failed to authenticate user '%s'" % user_name return False print "Super-Gluu. Authenticate for step 1. User '%s' successfully authenticated with u2f_device '%s'" % (user_name, u2f_device_id) return True elif self.twoStep: authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False if (self.use_super_gluu_group): print "Super-Gluu. Authenticate for step 1. Checking if user belong to super_gluu group" is_member_super_gluu_group = self.isUserMemberOfGroup(authenticated_user, self.audit_attribute, self.super_gluu_group) if (is_member_super_gluu_group): print "Super-Gluu. Authenticate for step 1. User '%s' member of super_gluu group" % authenticated_user.getUserId() super_gluu_count_login_steps = 2 else: if self.use_audit_group: self.processAuditGroup(authenticated_user, self.audit_attribute, self.audit_group) super_gluu_count_login_steps = 1 identity.setWorkingParameter("super_gluu_count_login_steps", super_gluu_count_login_steps) if super_gluu_count_login_steps == 1: return True auth_method = 'authenticate' enrollment_mode = ServerUtil.getFirstValue(requestParameters, "loginForm:registerButton") if StringHelper.isNotEmpty(enrollment_mode): auth_method = 'enroll' if auth_method == 'authenticate': user_inum = userService.getUserInum(authenticated_user) u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, client_redirect_uri, "oxId") if u2f_devices_list.size() == 0: auth_method = 'enroll' print "Super-Gluu. Authenticate for step 1. There is no U2F '%s' user devices associated with application '%s'. Changing auth_method to '%s'" % (user_name, client_redirect_uri, auth_method) print "Super-Gluu. Authenticate for step 1. auth_method: '%s'" % auth_method identity.setWorkingParameter("super_gluu_auth_method", auth_method) return True return False elif step == 2: print "Super-Gluu. Authenticate for step 2" user = authenticationService.getAuthenticatedUser() if (user == None): print "Super-Gluu. Authenticate for step 2. Failed to determine user name" return False user_name = user.getUserId() session_attributes = identity.getSessionId().getSessionAttributes() session_device_status = self.getSessionDeviceStatus(session_attributes, user_name) if session_device_status == None: return False u2f_device_id = session_device_status['device_id'] # There are two steps only in enrollment mode if self.oneStep and session_device_status['enroll']: authenticated_user = self.processBasicAuthentication(credentials) if authenticated_user == None: return False user_inum = userService.getUserInum(authenticated_user) attach_result = deviceRegistrationService.attachUserDeviceRegistration(user_inum, u2f_device_id) print "Super-Gluu. Authenticate for step 2. Result after attaching u2f_device '%s' to user '%s': '%s'" % (u2f_device_id, user_name, attach_result) return attach_result elif self.twoStep: if user_name == None: print "Super-Gluu. Authenticate for step 2. Failed to determine user name" return False validation_result = self.validateSessionDeviceStatus(client_redirect_uri, session_device_status, user_name) if validation_result: print "Super-Gluu. Authenticate for step 2. User '%s' successfully authenticated with u2f_device '%s'" % (user_name, u2f_device_id) else: return False super_gluu_request = json.loads(session_device_status['super_gluu_request']) auth_method = super_gluu_request['method'] if auth_method in ['enroll', 'authenticate']: if validation_result and self.use_audit_group: user = authenticationService.getAuthenticatedUser() self.processAuditGroup(user, self.audit_attribute, self.audit_group) return validation_result print "Super-Gluu. Authenticate for step 2. U2F auth_method is invalid" return False else: return False def prepareForStep(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) session_attributes = identity.getSessionId().getSessionAttributes() client_redirect_uri = self.getClientRedirecUri(session_attributes) if client_redirect_uri == None: print "Super-Gluu. Prepare for step. redirect_uri is not set" return False self.setRequestScopedParameters(identity, step) if step == 1: print "Super-Gluu. Prepare for step 1" if self.oneStep: session_id = CdiUtil.bean(SessionIdService).getSessionIdFromCookie() if StringHelper.isEmpty(session_id): print "Super-Gluu. Prepare for step 2. Failed to determine session_id" return False issuer = CdiUtil.bean(ConfigurationFactory).getConfiguration().getIssuer() super_gluu_request_dictionary = {'app': client_redirect_uri, 'issuer': issuer, 'state': session_id, 'created': datetime.datetime.now().isoformat()} self.addGeolocationData(session_attributes, super_gluu_request_dictionary) super_gluu_request = json.dumps(super_gluu_request_dictionary, separators=(',',':')) print "Super-Gluu. Prepare for step 1. Prepared super_gluu_request:", super_gluu_request identity.setWorkingParameter("super_gluu_request", super_gluu_request) elif self.twoStep: identity.setWorkingParameter("display_register_action", True) return True elif step == 2: print "Super-Gluu. Prepare for step 2" if self.oneStep: return True authenticationService = CdiUtil.bean(AuthenticationService) user = authenticationService.getAuthenticatedUser() if user == None: print "Super-Gluu. Prepare for step 2. Failed to determine user name" return False if session_attributes.containsKey("super_gluu_request"): super_gluu_request = session_attributes.get("super_gluu_request") if not StringHelper.equalsIgnoreCase(super_gluu_request, "timeout"): print "Super-Gluu. Prepare for step 2. Request was generated already" return True session_id = CdiUtil.bean(SessionIdService).getSessionIdFromCookie() if StringHelper.isEmpty(session_id): print "Super-Gluu. Prepare for step 2. Failed to determine session_id" return False auth_method = session_attributes.get("super_gluu_auth_method") if StringHelper.isEmpty(auth_method): print "Super-Gluu. Prepare for step 2. Failed to determine auth_method" return False print "Super-Gluu. Prepare for step 2. auth_method: '%s'" % auth_method issuer = CdiUtil.bean(ConfigurationFactory).getAppConfiguration().getIssuer() super_gluu_request_dictionary = {'username': user.getUserId(), 'app': client_redirect_uri, 'issuer': issuer, 'method': auth_method, 'state': session_id, 'created': datetime.datetime.now().isoformat()} self.addGeolocationData(session_attributes, super_gluu_request_dictionary) super_gluu_request = json.dumps(super_gluu_request_dictionary, separators=(',',':')) print "Super-Gluu. Prepare for step 2. Prepared super_gluu_request:", super_gluu_request identity.setWorkingParameter("super_gluu_request", super_gluu_request) identity.setWorkingParameter("super_gluu_auth_method", auth_method) if auth_method in ['authenticate']: self.sendPushNotification(client_redirect_uri, user, super_gluu_request) return True else: return False def getNextStep(self, configurationAttributes, requestParameters, step): # If user not pass current step change step to previous identity = CdiUtil.bean(Identity) retry_current_step = identity.getWorkingParameter("retry_current_step") if retry_current_step: print "Super-Gluu. Get next step. Retrying current step" # Remove old QR code identity.setWorkingParameter("super_gluu_request", "timeout") resultStep = step return resultStep return -1 def getExtraParametersForStep(self, configurationAttributes, step): if step == 1: if self.oneStep: return Arrays.asList("super_gluu_request") elif self.twoStep: return Arrays.asList("display_register_action") elif step == 2: return Arrays.asList("super_gluu_auth_method", "super_gluu_request") return None def getCountAuthenticationSteps(self, configurationAttributes): identity = CdiUtil.bean(Identity) if identity.isSetWorkingParameter("super_gluu_count_login_steps"): return identity.getWorkingParameter("super_gluu_count_login_steps") else: return 2 def getPageForStep(self, configurationAttributes, step): if step == 1: if self.oneStep: return "/auth/super-gluu/login.xhtml" elif step == 2: if self.oneStep: return "/login.xhtml" else: identity = CdiUtil.bean(Identity) authmethod = identity.getWorkingParameter("super_gluu_auth_method") print "Super-Gluu. authmethod '%s'" % authmethod if authmethod == "enroll": return "/auth/super-gluu/login.xhtml" else: return "/auth/super-gluu/login.xhtml" return "" def logout(self, configurationAttributes, requestParameters): return True def processBasicAuthentication(self, credentials): userService = CdiUtil.bean(UserService) authenticationService = CdiUtil.bean(AuthenticationService) 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 None find_user_by_uid = authenticationService.getAuthenticatedUser() if find_user_by_uid == None: print "Super-Gluu. Process basic authentication. Failed to find user '%s'" % user_name return None return find_user_by_uid def validateSessionDeviceStatus(self, client_redirect_uri, session_device_status, user_name = None): userService = CdiUtil.bean(UserService) deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) u2f_device_id = session_device_status['device_id'] u2f_device = None if session_device_status['enroll'] and session_device_status['one_step']: u2f_device = deviceRegistrationService.findOneStepUserDeviceRegistration(u2f_device_id) if u2f_device == None: print "Super-Gluu. Validate session device status. There is no one step u2f_device '%s'" % u2f_device_id return False else: # Validate if user has specified device_id enrollment user_inum = userService.getUserInum(user_name) if session_device_status['one_step']: user_inum = session_device_status['user_inum'] u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id) if u2f_device == None: print "Super-Gluu. Validate session device status. There is no u2f_device '%s' associated with user '%s'" % (u2f_device_id, user_inum) return False if not StringHelper.equalsIgnoreCase(client_redirect_uri, u2f_device.application): print "Super-Gluu. Validate session device status. u2f_device '%s' associated with other application '%s'" % (u2f_device_id, u2f_device.application) return False return True def getSessionDeviceStatus(self, session_attributes, user_name): print "Super-Gluu. Get session device status" if not session_attributes.containsKey("super_gluu_request"): print "Super-Gluu. Get session device status. There is no Super-Gluu request in session attributes" return None # Check session state extended if not session_attributes.containsKey("session_custom_state"): print "Super-Gluu. Get session device status. There is no session_custom_state in session attributes" return None session_custom_state = session_attributes.get("session_custom_state") if not StringHelper.equalsIgnoreCase("approved", session_custom_state): print "Super-Gluu. Get session device status. User '%s' not approve or not pass U2F authentication. session_custom_state: '%s'" % (user_name, session_custom_state) return None # Try to find device_id in session attribute if not session_attributes.containsKey("oxpush2_u2f_device_id"): print "Super-Gluu. Get session device status. There is no u2f_device associated with this request" return None # Try to find user_inum in session attribute if not session_attributes.containsKey("oxpush2_u2f_device_user_inum"): print "Super-Gluu. Get session device status. There is no user_inum associated with this request" return None enroll = False if session_attributes.containsKey("oxpush2_u2f_device_enroll"): enroll = StringHelper.equalsIgnoreCase("true", session_attributes.get("oxpush2_u2f_device_enroll")) one_step = False if session_attributes.containsKey("oxpush2_u2f_device_one_step"): one_step = StringHelper.equalsIgnoreCase("true", session_attributes.get("oxpush2_u2f_device_one_step")) super_gluu_request = session_attributes.get("super_gluu_request") u2f_device_id = session_attributes.get("oxpush2_u2f_device_id") user_inum = session_attributes.get("oxpush2_u2f_device_user_inum") session_device_status = {"super_gluu_request": super_gluu_request, "device_id": u2f_device_id, "user_inum" : user_inum, "enroll" : enroll, "one_step" : one_step} print "Super-Gluu. Get session device status. session_device_status: '%s'" % (session_device_status) return session_device_status def initPushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize Native/SNS/Gluu notification services" self.pushSnsMode = False self.pushGluuMode = False if configurationAttributes.containsKey("notification_service_mode"): notificationServiceMode = configurationAttributes.get("notification_service_mode").getValue2() if StringHelper.equalsIgnoreCase(notificationServiceMode, "sns"): return self.initSnsPushNotificationService(configurationAttributes) elif StringHelper.equalsIgnoreCase(notificationServiceMode, "gluu"): return self.initGluuPushNotificationService(configurationAttributes) return self.initNativePushNotificationService(configurationAttributes) def initNativePushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize native notification services" creds = self.loadPushNotificationCreds(configurationAttributes) if creds == None: return False try: android_creds = creds["android"]["gcm"] ios_creds = creds["ios"]["apns"] except: print "Super-Gluu. Initialize native notification services. Invalid credentials file format" return False self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu. Initialize native notification services. Created Android notification service" if ios_creds["enabled"]: p12_file_path = ios_creds["p12_file_path"] p12_passowrd = ios_creds["p12_password"] try: encryptionService = CdiUtil.bean(EncryptionService) p12_passowrd = encryptionService.decrypt(p12_passowrd) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize native notification services. Assuming that 'p12_passowrd' password in not encrypted" apnsServiceBuilder = APNS.newService().withCert(p12_file_path, p12_passowrd) if ios_creds["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination().build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build() self.pushAppleServiceProduction = ios_creds["production"] print "Super-Gluu. Initialize native notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled def initSnsPushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize SNS notification services" self.pushSnsMode = True creds = self.loadPushNotificationCreds(configurationAttributes) if creds == None: return False try: sns_creds = creds["sns"] android_creds = creds["android"]["sns"] ios_creds = creds["ios"]["sns"] except: print "Super-Gluu. Initialize SNS notification services. Invalid credentials file format" return False self.pushAndroidService = None self.pushAppleService = None if not (android_creds["enabled"] or ios_creds["enabled"]): print "Super-Gluu. Initialize SNS notification services. SNS disabled for all platforms" return False sns_access_key = sns_creds["access_key"] sns_secret_access_key = sns_creds["secret_access_key"] sns_region = sns_creds["region"] encryptionService = CdiUtil.bean(EncryptionService) try: sns_secret_access_key = encryptionService.decrypt(sns_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize SNS notification services. Assuming that 'sns_secret_access_key' in not encrypted" pushSnsService = CdiUtil.bean(PushSnsService) pushClient = pushSnsService.createSnsClient(sns_access_key, sns_secret_access_key, sns_region) if android_creds["enabled"]: self.pushAndroidService = pushClient self.pushAndroidPlatformArn = android_creds["platform_arn"] print "Super-Gluu. Initialize SNS notification services. Created Android notification service" if ios_creds["enabled"]: self.pushAppleService = pushClient self.pushApplePlatformArn = ios_creds["platform_arn"] self.pushAppleServiceProduction = ios_creds["production"] print "Super-Gluu. Initialize SNS notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled def initGluuPushNotificationService(self, configurationAttributes): print "Super-Gluu. Initialize Gluu notification services" self.pushGluuMode = True creds = self.loadPushNotificationCreds(configurationAttributes) if creds == None: return False try: gluu_conf = creds["gluu"] android_creds = creds["android"]["gluu"] ios_creds = creds["ios"]["gluu"] except: print "Super-Gluu. Initialize Gluu notification services. Invalid credentials file format" return False self.pushAndroidService = None self.pushAppleService = None if not (android_creds["enabled"] or ios_creds["enabled"]): print "Super-Gluu. Initialize Gluu notification services. Gluu disabled for all platforms" return False gluu_server_uri = gluu_conf["server_uri"] notifyClientFactory = NotifyClientFactory.instance() metadataConfiguration = None try: metadataConfiguration = notifyClientFactory.createMetaDataConfigurationService(gluu_server_uri).getMetadataConfiguration() except: print "Super-Gluu. Initialize Gluu notification services. Failed to load metadata. Exception: ", sys.exc_info()[1] return False gluuClient = notifyClientFactory.createNotifyService(metadataConfiguration) encryptionService = CdiUtil.bean(EncryptionService) if android_creds["enabled"]: gluu_access_key = android_creds["access_key"] gluu_secret_access_key = android_creds["secret_access_key"] try: gluu_secret_access_key = encryptionService.decrypt(gluu_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize Gluu notification services. Assuming that 'gluu_secret_access_key' in not encrypted" self.pushAndroidService = gluuClient self.pushAndroidServiceAuth = notifyClientFactory.getAuthorization(gluu_access_key, gluu_secret_access_key); print "Super-Gluu. Initialize Gluu notification services. Created Android notification service" if ios_creds["enabled"]: gluu_access_key = ios_creds["access_key"] gluu_secret_access_key = ios_creds["secret_access_key"] try: gluu_secret_access_key = encryptionService.decrypt(gluu_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu. Initialize Gluu notification services. Assuming that 'gluu_secret_access_key' in not encrypted" self.pushAppleService = gluuClient self.pushAppleServiceAuth = notifyClientFactory.getAuthorization(gluu_access_key, gluu_secret_access_key); print "Super-Gluu. Initialize Gluu notification services. Created iOS notification service" enabled = self.pushAndroidService != None or self.pushAppleService != None return enabled def loadPushNotificationCreds(self, configurationAttributes): print "Super-Gluu. Initialize notification services" if not configurationAttributes.containsKey("credentials_file"): return None super_gluu_creds_file = configurationAttributes.get("credentials_file").getValue2() # Load credentials from file f = open(super_gluu_creds_file, 'r') try: creds = json.loads(f.read()) except: print "Super-Gluu. Initialize notification services. Failed to load credentials from file:", super_gluu_creds_file return None finally: f.close() return creds def sendPushNotification(self, client_redirect_uri, user, super_gluu_request): try: self.sendPushNotificationImpl(client_redirect_uri, user, super_gluu_request) except: print "Super-Gluu. Send push notification. Failed to send push notification: ", sys.exc_info()[1] def sendPushNotificationImpl(self, client_redirect_uri, user, super_gluu_request): if not self.enabledPushNotifications: return user_name = user.getUserId() print "Super-Gluu. Send push notification. Loading user '%s' devices" % user_name send_notification = False send_notification_result = True userService = CdiUtil.bean(UserService) deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) user_inum = userService.getUserInum(user_name) send_android = 0 send_ios = 0 u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, client_redirect_uri, "oxId", "oxDeviceData", "oxDeviceNotificationConf") if u2f_devices_list.size() > 0: for u2f_device in u2f_devices_list: device_data = u2f_device.getDeviceData() # Device data which Super-Gluu gets during enrollment if device_data == None: continue platform = device_data.getPlatform() push_token = device_data.getPushToken() debug = False if StringHelper.equalsIgnoreCase(platform, "ios") and StringHelper.isNotEmpty(push_token): # Sending notification to iOS user's device if self.pushAppleService == None: print "Super-Gluu. Send push notification. Apple native push notification service is not enabled" else: send_notification = True title = "Super-Gluu" message = "Super-Gluu login request to: %s" % client_redirect_uri if self.pushSnsMode or self.pushGluuMode: pushSnsService = CdiUtil.bean(PushSnsService) targetEndpointArn = self.getTargetEndpointArn(deviceRegistrationService, pushSnsService, PushPlatform.APNS, user, u2f_device) if targetEndpointArn == None: return send_notification = True sns_push_request_dictionary = { "aps": { "badge": 0, "alert" : {"body": message, "title" : title}, "category": "ACTIONABLE", "content-available": "1", "sound": 'default' }, "request" : super_gluu_request } push_message = json.dumps(sns_push_request_dictionary, separators=(',',':')) if self.pushSnsMode: apple_push_platform = PushPlatform.APNS if not self.pushAppleServiceProduction: apple_push_platform = PushPlatform.APNS_SANDBOX send_notification_result = pushSnsService.sendPushMessage(self.pushAppleService, apple_push_platform, targetEndpointArn, push_message, None) if debug: print "Super-Gluu. Send iOS SNS push notification. token: '%s', message: '%s', send_notification_result: '%s', apple_push_platform: '%s'" % (push_token, push_message, send_notification_result, apple_push_platform) elif self.pushGluuMode: send_notification_result = self.pushAppleService.sendNotification(self.pushAppleServiceAuth, targetEndpointArn, push_message) if debug: print "Super-Gluu. Send iOS Gluu push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) else: additional_fields = { "request" : super_gluu_request } msgBuilder = APNS.newPayload().alertBody(message).alertTitle(title).sound("default") msgBuilder.category('ACTIONABLE').badge(0) msgBuilder.forNewsstand() msgBuilder.customFields(additional_fields) push_message = msgBuilder.build() send_notification_result = self.pushAppleService.push(push_token, push_message) if debug: print "Super-Gluu. Send iOS Native push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) send_ios = 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. Send native push notification. Android native push notification service is not enabled" else: send_notification = True title = "Super-Gluu" if self.pushSnsMode or self.pushGluuMode: pushSnsService = CdiUtil.bean(PushSnsService) targetEndpointArn = self.getTargetEndpointArn(deviceRegistrationService, pushSnsService, PushPlatform.GCM, user, u2f_device) if targetEndpointArn == None: return send_notification = True sns_push_request_dictionary = { "collapse_key": "single", "content_available": True, "time_to_live": 60, "data": { "message" : super_gluu_request, "title" : title } } push_message = json.dumps(sns_push_request_dictionary, separators=(',',':')) if self.pushSnsMode: send_notification_result = pushSnsService.sendPushMessage(self.pushAndroidService, PushPlatform.GCM, targetEndpointArn, push_message, None) if debug: print "Super-Gluu. Send Android SNS push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) elif self.pushGluuMode: send_notification_result = self.pushAndroidService.sendNotification(self.pushAndroidServiceAuth, targetEndpointArn, push_message) if debug: print "Super-Gluu. Send Android Gluu push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) else: msgBuilder = Message.Builder().addData("message", super_gluu_request).addData("title", title).collapseKey("single").contentAvailable(True) push_message = msgBuilder.build() send_notification_result = self.pushAndroidService.send(push_message, push_token, 3) if debug: print "Super-Gluu. Send Android Native push notification. token: '%s', message: '%s', send_notification_result: '%s'" % (push_token, push_message, send_notification_result) send_android = send_android + 1 print "Super-Gluu. Send push notification. send_android: '%s', send_ios: '%s'" % (send_android, send_ios) def getTargetEndpointArn(self, deviceRegistrationService, pushSnsService, platform, user, u2fDevice): targetEndpointArn = None # Return endpoint ARN if it 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. Get target endpoint ARN. There is already created target endpoint ARN" 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: return None deviceData = u2fDevice.getDeviceData() pushToken = deviceData.getPushToken() print "Super-Gluu. Get target endpoint ARN. Attempting to create target endpoint ARN for user: '******'" % 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. Failed to get endpoint ARN for user: '******'" % user.getUserId() return None print "Super-Gluu. Get target endpoint ARN. Create target endpoint ARN '%s' for user: '******'" % (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 getClientRedirecUri(self, session_attributes): if not session_attributes.containsKey("redirect_uri"): return None return session_attributes.get("redirect_uri") def setRequestScopedParameters(self, identity, step): downloadMap = HashMap() if self.registrationUri != None: identity.setWorkingParameter("external_registration_uri", self.registrationUri) if self.androidUrl!= None and step == 1: downloadMap.put("android", self.androidUrl) if self.IOSUrl != None and step == 1: downloadMap.put("ios", self.IOSUrl) if self.customLabel != None: identity.setWorkingParameter("super_gluu_label", self.customLabel) identity.setWorkingParameter("download_url",downloadMap) identity.setWorkingParameter("super_gluu_qr_options", self.customQrOptions) def addGeolocationData(self, session_attributes, super_gluu_request_dictionary): if session_attributes.containsKey("remote_ip"): remote_ip = session_attributes.get("remote_ip") if StringHelper.isNotEmpty(remote_ip): print "Super-Gluu. Prepare for step 2. Adding req_ip and req_loc to super_gluu_request" super_gluu_request_dictionary['req_ip'] = remote_ip remote_loc_dic = self.determineGeolocationData(remote_ip) if remote_loc_dic == None: print "Super-Gluu. Prepare for step 2. Failed to determine remote location by remote IP '%s'" % remote_ip return remote_loc = "%s, %s, %s" % ( remote_loc_dic['country'], remote_loc_dic['regionName'], remote_loc_dic['city'] ) remote_loc_encoded = urllib.quote(remote_loc) super_gluu_request_dictionary['req_loc'] = remote_loc_encoded def determineGeolocationData(self, remote_ip): print "Super-Gluu. Determine remote location. remote_ip: '%s'" % remote_ip httpService = CdiUtil.bean(HttpService) http_client = httpService.getHttpsClient() http_client_params = http_client.getParams() http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000) geolocation_service_url = "http://ip-api.com/json/%s?fields=49177" % 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 "Super-Gluu. Determine remote location. Exception: ", sys.exc_info()[1] return None try: if not httpService.isResponseStastusCodeOk(http_response): print "Super-Gluu. Determine remote location. Get invalid response from validation server: ", str(http_response.getStatusLine().getStatusCode()) httpService.consume(http_response) return None response_bytes = httpService.getResponseContent(http_response) response_string = httpService.convertEntityToString(response_bytes) httpService.consume(http_response) finally: http_service_response.closeConnection() if response_string == None: print "Super-Gluu. Determine remote location. Get empty response from location server" return None response = json.loads(response_string) if not StringHelper.equalsIgnoreCase(response['status'], "success"): print "Super-Gluu. Determine remote location. Get response with status: '%s'" % response['status'] return None return response def isUserMemberOfGroup(self, user, attribute, group): is_member = False member_of_list = user.getAttributeValues(attribute) if (member_of_list != None): for member_of in member_of_list: if StringHelper.equalsIgnoreCase(group, member_of) or member_of.endswith(group): is_member = True break return is_member def processAuditGroup(self, user, attribute, group): is_member = self.isUserMemberOfGroup(user, attribute, group) if (is_member): print "Super-Gluu. Authenticate for processAuditGroup. User '%s' member of audit group" % user.getUserId() print "Super-Gluu. Authenticate for processAuditGroup. Sending e-mail about user '%s' login to %s" % (user.getUserId(), self.audit_email) # Send e-mail to administrator user_id = user.getUserId() mailService = CdiUtil.bean(MailService) subject = "User log in: %s" % user_id body = "User log in: %s" % user_id mailService.sendMail(self.audit_email, subject, body)
class PushNotificationManager: def __init__(self, serviceMode, credentialsFile): self.pushSnsMode = False self.pushGluuMode = False self.pushNotificationsEnabled = False self.titleTemplate = "Super-Gluu" self.messageTemplate = "Super-Gluu login request to %s" self.debugEnabled = True self.httpConnTimeout = 15 * 1000 # in milliseconds creds = self.loadCredentials(credentialsFile) if creds == None: return None if StringHelper.equalsIgnoreCase(serviceMode, "sns"): self.initSnsPushNotifications(creds) elif StringHelper.equalsIgnoreCase(serviceMode, "gluu"): self.initGluuPushNotifications(creds) else: self.initNativePushNotifications(creds) def initSnsPushNotifications(self, creds): print "Super-Gluu-Push. SNS push notifications init ..." self.pushSnsMode = True try: sns_creds = creds["sns"] android_creds = creds["android"]["sns"] ios_creds = creds["ios"]["sns"] except: print "Super-Gluu-Push. Invalid SNS credentials format" return None self.pushAndroidService = None self.pushAppleService = None if not (android_creds["enabled"] or ios_creds["enabled"]): print "Super-Gluu-Push. SNS disabled for all platforms" return None sns_access_key = sns_creds["access_key"] sns_secret_access_key = sns_creds["secret_access_key"] sns_region = sns_creds["region"] encryptionService = CdiUtil.bean(EncryptionService) try: sns_secret_access_key = encryptionService.decrypt( sns_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'sns_access_key' is not encrypted" pushSnsService = CdiUtil.bean(PushSnsService) pushClient = pushSnsService.createSnsClient(sns_access_key, sns_secret_access_key, sns_region) if android_creds["enabled"]: self.pushAndroidService = pushClient self.pushAndroidPlatformArn = android_creds["platform_arn"] print "Super-Gluu-Push. Created SNS android notification service" if ios_creds["enabled"]: self.pushAppleService = pushClient self.pushApplePlatformArn = ios_creds["platform_arn"] self.pushAppleServiceProduction = ios_creds["production"] self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None def initGluuPushNotifications(self, creds): print "Super-Gluu-Push. Gluu push notifications init ... " self.pushGluuMode = True try: gluu_conf = creds["gluu"] android_creds = creds["android"]["gluu"] ios_creds = creds["ios"]["gluu"] except: print "Super-Gluu-Push. Invalid Gluu credentials format" return None self.pushAndroidService = None self.pushAppleService = None if not (android_creds["enabled"] or ios_creds["enabled"]): print "Super-Gluu-Push. Gluu disabled for all platforms" return None gluu_server_uri = gluu_conf["server_uri"] notifyClientFactory = NotifyClientFactory.instance() metadataConfiguration = self.getNotifyMetadata(gluu_server_uri) if metadataConfiguration == None: return None gluuClient = notifyClientFactory.createNotifyService( metadataConfiguration) encryptionService = CdiUtil.bean(EncryptionService) if android_creds["enabled"]: gluu_access_key = android_creds["access_key"] gluu_secret_access_key = android_creds["secret_access_key"] try: gluu_secret_access_key = encryptionService.decrypt( gluu_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'gluu_secret_access_key' is not encrypted" self.pushAndroidService = gluuClient self.pushAndroidServiceAuth = notifyClientFactory.getAuthorization( gluu_access_key, gluu_secret_access_key) print "Super-Gluu-Push. Created Gluu Android notification service" if ios_creds["enabled"]: gluu_access_key = ios_creds["access_key"] gluu_secret_access_key = ios_creds["secret_access_key"] try: gluu_secret_access_key = encryptionService.decrypt( gluu_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'gluu_secret_access_key' is not encrypted" self.pushAppleService = gluuClient self.pushAppleServiceAuth = notifyClientFactory.getAuthorization( gluu_access_key, gluu_secret_access_key) print "Super-Gluu-Push. Created Gluu iOS notification service" self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None def initNativePushNotifications(self, creds): print "Super-Gluu-Push. Native push notifications init ... " try: android_creds = creds["android"]["gcm"] ios_creds = creds["ios"]["apns"] except: print "Super-Gluu-Push. Invalid credentials format" return None self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu-Push. Created native Android notification service" if ios_creds["enabled"]: p12_file_path = ios_creds["p12_file_path"] p12_password = ios_creds["p12_password"] try: encryptionService = CdiUtil.bean(EncryptionService) p12_password = encryptionService.decrypt(p12_password) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'p12_password' is not encrypted" apnsServiceBuilder = APNS.newService().withCert( p12_file_path, p12_password) if ios_creds["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination( ).build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination( ).build() self.pushAppleServiceProduction = ios_creds["production"] print "Super-Gluu-Push. Created native iOS notification service" self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None def loadCredentials(self, credentialsFile): print "Super-Gluu-Push. Loading credentials ... " f = open(credentialsFile, 'r') try: creds = json.loads(f.read()) print "Super-Gluu-Push. Credentials loaded successfully" except: exception_value = sys.exc_info()[1] print "Super-Gluu-Push. Loading credentials failed.", exception_value return None finally: f.close() return creds def getNotifyMetadata(self, gluu_server_uri): try: notifyClientFactory = NotifyClientFactory.instance() metadataConfigurationService = notifyClientFactory.createMetaDataConfigurationService( gluu_server_uri) return metadataConfigurationService.getMetadataConfiguration() except: exc_value = sys.exc_info()[1] print "Super-Gluu-Push. Gluu push notification init failed while loading metadata. %s." % exc_value print "Super-Gluu-Push. Retrying loading metadata using httpService..." httpService = CdiUtil.bean(HttpService) http_client = httpService.getHttpsClient() http_client_params = http_client.getParams() http_client_params.setIntParameter( CoreConnectionPNames.CONNECTION_TIMEOUT, self.httpConnTimeout) notify_service_url = "%s/.well-known/notify-configuration" % gluu_server_uri notify_service_headers = {"Accept": "application/json"} try: http_service_response = httpService.executeGet( http_client, notify_service_url, notify_service_headers) if http_service_response == None: print "Super-Gluu-Push. Loading metadata using httpService failed. Nil http_service_response" return None http_response = http_service_response.getHttpResponse() except: print "Super-Gluu-Push. Loading metadata using httpService failed. %s." % sys.exc_info( )[1] return None try: if not httpService.isResponseStastusCodeOk(http_response): http_error_str = str( http_response.getStatusLine().getStatusCode()) print "Super-Gluu-Push. Loading metadata using httpService failed with http code %s." % http_error_str httpService.consume(http_response) return None resp_bytes = httpService.getResponseContent(http_response) resp_str = httpService.convertEntityToString(resp_bytes) httpService.consume(http_response) except: print "Super-Gluu-Push. Loading metadata using httpService failed. %s." % sys.exc_info( )[1] return None finally: http_service_response.closeConnection() if resp_str == None: print "Super-Gluu-Push. Loading metadata using httpService failed.Empty response from server" return None json_resp = json.loads(resp_str) if ('version' not in json_resp) or ('issuer' not in json_resp): print "Super-Gluu-Push. Loading metadata using httpService failed. Invalid json response %s." % json_resp return None if ('notify_endpoint' not in json_resp) and ('notifyEndpoint' not in json_resp): print "Super-Gluu-Push. Loading metadata using httpService failed. Invalid json response %s." % json_resp return None notifyMeta = NotifyMetadata() notifyMeta.setVersion(json_resp['version']) notifyMeta.setIssuer(json_resp['issuer']) if 'notify_endpoint' in json_resp: notifyMeta.setNotifyEndpoint(json_resp['notify_endpoint']) elif 'notifyEndpoint' in json_resp: notifyMeta.setNotifyEndpoint(json_resp['notifyEndpoint']) print "Super-Gluu-Push. Metadata loaded using httpService successfully" return notifyMeta def sendPushNotification(self, user, app_id, super_gluu_request): try: return self.sendPushNotificationImpl(user, app_id, super_gluu_request) except InternalServerErrorException as is_error: print "Super-Gluu-Push. Failed to send push notification : '%s'" % is_error.getMessage( ) return 0 except: exception_value = sys.exc_info()[1] print "Super-Gluu-Push. Failed to send push notification :" % exception_value return 0 def sendPushNotificationImpl(self, user, app_id, super_gluu_request): if not self.pushNotificationsEnabled: print "Super-Gluu-Push. Push notifications are disabled" return None user_name = user.getUserId() print "Super-Gluu-Push. Sending push notification to user '%s' devices" % user_name userService = CdiUtil.bean(UserService) deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) user_inum = userService.getUserInum(user_name) u2f_device_list = deviceRegistrationService.findUserDeviceRegistrations( user_inum, app_id, "oxId", "oxDeviceData", "oxDeviceNotificationConf") send_ios = 0 send_android = 0 if u2f_device_list.size() > 0: for u2f_device in u2f_device_list: print "Super-Gluu-Push. Send device notification to device" device_push_result = self.sendDevicePushNotification( user, app_id, u2f_device, super_gluu_request) send_ios += device_push_result["send_ios"] send_android += device_push_result["send_android"] else: print "Super-Gluu-Push. No device enrolled for user '%s'" % user_name return 0 msg = """Super-Gluu-Push. Send push notification. send_android: '%s', send_ios: '%s' """ print msg % (send_android, send_ios) return send_android + send_ios 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 sendApplePushNotification(self, pushNotificationContext): if self.pushSnsMode or self.pushGluuMode: if self.pushSnsMode: self.sendApplePushSnsNotification(pushNotificationContext) elif self.pushGluuMode: self.sendApplePushGluuNotification(pushNotificationContext) else: self.sendApplePushNativeNotification(pushNotificationContext) def sendAndroidPushNotification(self, pushNotificationContext): if self.pushSnsMode or self.pushGluuMode: if self.pushSnsMode: self.sendAndroidPushSnsNotification(pushNotificationContext) elif self.pushGluuMode: self.sendAndroidPushGluuNotification(pushNotificationContext) else: self.sendAndroidPushNativeNotification(pushNotificationContext) def sendApplePushSnsNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled apple_push_platform = PushPlatform.APNS targetEndpointArn = self.getTargetEndpointArn(apple_push_platform, pushNotificationContext) if targetEndpointArn == None: return None push_message = self.buildApplePushMessage(pushNotificationContext) apple_push_platform = PushPlatform.APNS if not self.pushAppleServiceProduction: apple_push_platform = PushPlatform.APNS_SANDBOX pushSnsService = pushNotificationContext.pushSnsService send_notification_result = pushSnsService.sendPushMessage( self.pushAppleService, apple_push_platform, targetEndpointArn, push_message, None) if debug: dbg_msg = """Super-Gluu-Push. Send iOS SNS push notification. message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_message, send_notification_result) def sendAndroidPushSnsNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled android_push_platform = PushPlatform.GCM targetEndpointArn = self.getTargetEndpointArn(android_push_platform, pushNotificationContext) if targetEndpointArn == None: return None pushSnsService = pushNotificationContext.pushSnsService push_message = self.buildAndroidPushMessage(pushNotificationContext) send_notification_result = pushSnsService.sendPushMessage( self.pushAndroidService, android_push_platform, targetEndpointArn, push_message, None) if debug: dbg_msg = """Super-Gluu-Push. Send Android SNS push notification. message:'%s', send_notification_result: '%s'""" print dbg_msg % (push_message, send_notification_result) def sendApplePushGluuNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled apple_push_platform = PushPlatform.APNS targetEndpointArn = self.getTargetEndpointArn(apple_push_platform, pushNotificationContext) if targetEndpointArn == None: return None push_message = self.buildApplePushMessage(pushNotificationContext) print "push message : %s" % push_message send_notification_result = self.pushAppleService.sendNotification( self.pushAppleServiceAuth, targetEndpointArn, push_message) print "push message sent" if debug: dbg_msg = """Super-Gluu-Push. Send iOS gluu push notification. message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_message, send_notification_result) def sendAndroidPushGluuNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled android_push_platform = PushPlatform.GCM targetEndpointArn = self.getTargetEndpointArn(android_push_platform, pushNotificationContext) if targetEndpointArn == None: return None push_message = self.buildAndroidPushMessage(pushNotificationContext) send_notification_result = self.pushAndroidService.sendNotification( self.pushAndroidServiceAuth, targetEndpointArn, push_message) if debug: dbg_msg = """Super-Gluu-Push. Send Android gluu push notification. message: '%s', send_notification_result: '%s' """ print dbg_msg % (push_message, send_notification_result) pass def sendApplePushNativeNotification(self, pushNotificationContext): title = self.titleTemplate message = self.messageTemplate % pushNotificationContext.appId push_token = pushNotificationContext.pushToken additional_fields = { "request": pushNotificationContext.superGluuRequest } debug = pushNotificationContext.debugEnabled msgBuilder = APNS.newPayload().alertBody(message).alertTitle( title).sound("default") msgBuilder.forNewsstand() msgBuilder.customFields(additional_fields) push_message = msgBuilder.build() send_notification_result = self.pushAppleService.push( push_token, push_message) if debug: dbg_msg = """Super-Gluu-Push. Send iOS native push notification. push_token:'%s', message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_token, push_message, send_notification_result) def sendAndroidPushNativeNotification(self, pushNotificationContext): title = self.titleTemplate superGluuRequest = pushNotificationContext.superGluuRequest msgBuilder = Message.Builder().addData( "message", superGluuRequest).addData( "title", title).collapseKey("single").contentAvailable(True) push_message = msgBuilder.build() push_token = pushNotificationContext.pushToken send_notification_result = self.pushAndroidService.send( push_message, push_token, 3) if pushNotificationContext.debugEnabled: dbg_msg = """Super-Gluu-Push. Send iOS native push notification. push_token:'%s', message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_token, push_message, send_notification_result) def buildApplePushMessage(self, pushNotificationContext): title = self.titleTemplate message = self.messageTemplate % pushNotificationContext.appId sns_push_request_dictionary = { "request": pushNotificationContext.superGluuRequest, "aps": { "badge": 0, "alert": { "body": message, "title": title }, "category": "ACTIONABLE", "content-available": "1", "sound": "default" } } return json.dumps(sns_push_request_dictionary, separators=(',', ':')) def buildAndroidPushMessage(self, pushNotificationContext): sns_push_request_dictionary = { "collapse_key": "single", "content_available": True, "time_to_live": 60, "data": { "message": pushNotificationContext.superGluuRequest, "title": self.titleTemplate } } return json.dumps(sns_push_request_dictionary, separators=(',', ':')) 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
class PushNotificationManager: def __init__(self, serviceMode, credentialsFile): self.pushSnsMode = False self.pushGluuMode = False self.pushNotificationsEnabled = False self.titleTemplate = "Super-Gluu" self.messageTemplate = "Super-Gluu login request to %s" self.debugEnabled = True self.httpConnTimeout = 15 * 1000 # in milliseconds creds = self.loadCredentials(credentialsFile) if creds == None: return None if StringHelper.equalsIgnoreCase(serviceMode,"sns"): self.initSnsPushNotifications(creds) elif StringHelper.equalsIgnoreCase(serviceMode,"gluu"): self.initGluuPushNotifications(creds) else: self.initNativePushNotifications(creds) def initSnsPushNotifications(self, creds): print "Super-Gluu-Push. SNS push notifications init ..." self.pushSnsMode = True try: sns_creds = creds["sns"] android_creds = creds["android"]["sns"] ios_creds = creds["ios"]["sns"] except: print "Super-Gluu-Push. Invalid SNS credentials format" return None self.pushAndroidService = None self.pushAppleService = None if not (android_creds["enabled"] or ios_creds["enabled"]): print "Super-Gluu-Push. SNS disabled for all platforms" return None sns_access_key = sns_creds["access_key"] sns_secret_access_key = sns_creds["secret_access_key"] sns_region = sns_creds["region"] encryptionService = CdiUtil.bean(EncryptionService) try: sns_secret_access_key = encryptionService.decrypt(sns_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'sns_access_key' is not encrypted" pushSnsService = CdiUtil.bean(PushSnsService) pushClient = pushSnsService.createSnsClient(sns_access_key,sns_secret_access_key,sns_region) if android_creds["enabled"]: self.pushAndroidService = pushClient self.pushAndroidPlatformArn = android_creds["platform_arn"] print "Super-Gluu-Push. Created SNS android notification service" if ios_creds["enabled"]: self.pushAppleService = pushClient self.pushApplePlatformArn = ios_creds["platform_arn"] self.pushAppleServiceProduction = ios_creds["production"] self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None def initGluuPushNotifications(self, creds): print "Super-Gluu-Push. Gluu push notifications init ... " self.pushGluuMode = True try: gluu_conf = creds["gluu"] android_creds = creds["android"]["gluu"] ios_creds = creds["ios"]["gluu"] except: print "Super-Gluu-Push. Invalid Gluu credentials format" return None self.pushAndroidService = None self.pushAppleService = None if not(android_creds["enabled"] or ios_creds["enabled"]): print "Super-Gluu-Push. Gluu disabled for all platforms" return None gluu_server_uri = gluu_conf["server_uri"] notifyClientFactory = NotifyClientFactory.instance() metadataConfiguration = self.getNotifyMetadata(gluu_server_uri) if metadataConfiguration == None: return None gluuClient = notifyClientFactory.createNotifyService(metadataConfiguration) encryptionService = CdiUtil.bean(EncryptionService) if android_creds["enabled"]: gluu_access_key = android_creds["access_key"] gluu_secret_access_key = android_creds["secret_access_key"] try: gluu_secret_access_key = encryptionService.decrypt(gluu_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'gluu_secret_access_key' is not encrypted" self.pushAndroidService = gluuClient self.pushAndroidServiceAuth = notifyClientFactory.getAuthorization(gluu_access_key,gluu_secret_access_key) print "Super-Gluu-Push. Created Gluu Android notification service" if ios_creds["enabled"]: gluu_access_key = ios_creds["access_key"] gluu_secret_access_key = ios_creds["secret_access_key"] try: gluu_secret_access_key = encryptionService.decrypt(gluu_secret_access_key) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'gluu_secret_access_key' is not encrypted" self.pushAppleService = gluuClient self.pushAppleServiceAuth = notifyClientFactory.getAuthorization(gluu_access_key,gluu_secret_access_key) print "Super-Gluu-Push. Created Gluu iOS notification service" self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None def initNativePushNotifications(self, creds): print "Super-Gluu-Push. Native push notifications init ... " try: android_creds = creds["android"]["gcm"] ios_creds = creds["ios"]["apns"] except: print "Super-Gluu-Push. Invalid credentials format" return None self.pushAndroidService = None self.pushAppleService = None if android_creds["enabled"]: self.pushAndroidService = Sender(android_creds["api_key"]) print "Super-Gluu-Push. Created native Android notification service" if ios_creds["enabled"]: p12_file_path = ios_creds["p12_file_path"] p12_password = ios_creds["p12_password"] try: encryptionService = CdiUtil.bean(EncryptionService) p12_password = encryptionService.decrypt(p12_password) except: # Ignore exception. Password is not encrypted print "Super-Gluu-Push. Assuming 'p12_password' is not encrypted" apnsServiceBuilder = APNS.newService().withCert(p12_file_path,p12_password) if ios_creds["production"]: self.pushAppleService = apnsServiceBuilder.withProductionDestination().build() else: self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build() self.pushAppleServiceProduction = ios_creds["production"] print "Super-Gluu-Push. Created native iOS notification service" self.pushNotificationsEnabled = self.pushAndroidService != None or self.pushAppleService != None def loadCredentials(self, credentialsFile): print "Super-Gluu-Push. Loading credentials ... " f = open(credentialsFile,'r') try: creds = json.loads(f.read()) print "Super-Gluu-Push. Credentials loaded successfully" except: exception_value = sys.exc_info()[1] print "Super-Gluu-Push. Loading credentials failed.", exception_value return None finally: f.close() return creds def getNotifyMetadata(self, gluu_server_uri): try: notifyClientFactory = NotifyClientFactory.instance() metadataConfigurationService = notifyClientFactory.createMetaDataConfigurationService(gluu_server_uri) return metadataConfigurationService.getMetadataConfiguration() except: exc_value = sys.exc_info()[1] print "Super-Gluu-Push. Gluu push notification init failed while loading metadata. %s." % exc_value print "Super-Gluu-Push. Retrying loading metadata using httpService..." httpService = CdiUtil.bean(HttpService) http_client = httpService.getHttpsClient() http_client_params = http_client.getParams() http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,self.httpConnTimeout) notify_service_url = "%s/.well-known/notify-configuration" % gluu_server_uri notify_service_headers = {"Accept": "application/json"} try: http_service_response = httpService.executeGet(http_client,notify_service_url,notify_service_headers) http_response = http_service_response.getHttpResponse() except: print "Super-Gluu-Push. Loading metadata using httpService failed. %s." % sys.exc_info()[1] return None try: if not httpService.isResponseStastusCodeOk(http_response): http_error_str = str(http_response.getStatusLine().getStatusCode()) print "Super-Gluu-Push. Loading metadata using httpService failed with http code %s." % http_error_str httpService.consume(http_response) return None resp_bytes = httpService.getResponseContent(http_response) resp_str = httpService.convertEntityToString(resp_bytes) httpService.consume(http_response) except: print "Super-Gluu-Push. Loading metadata using httpService failed. %s." % sys.exc_info()[1] return None finally: http_service_response.closeConnection() if resp_str == None: print "Super-Gluu-Push. Loading metadata using httpService failed.Empty response from server" return None json_resp = json.loads(resp_str) if ('version' not in json_resp) or ('issuer' not in json_resp): print "Super-Gluu-Push. Loading metadata using httpService failed. Invalid json response %s." % json_resp return None if ('notify_endpoint' not in json_resp) and ('notifyEndpoint' not in json_resp): print "Super-Gluu-Push. Loading metadata using httpService failed. Invalid json response %s." % json_resp return None notifyMeta = NotifyMetadata() notifyMeta.setVersion(json_resp['version']) notifyMeta.setIssuer(json_resp['issuer']) if 'notify_endpoint' in json_resp: notifyMeta.setNotifyEndpoint(json_resp['notify_endpoint']) elif 'notifyEndpoint' in json_resp: notifyMeta.setNotifyEndpoint(json_resp['notifyEndpoint']) print "Super-Gluu-Push. Metadata loaded using httpService successfully" return notifyMeta def sendPushNotification(self, user, app_id, super_gluu_request): try: return self.sendPushNotificationImpl(user, app_id, super_gluu_request) except InternalServerErrorException as is_error: print "Super-Gluu-Push. Failed to send push notification : '%s'" % is_error.getMessage() return 0 except: exception_value = sys.exc_info()[1] print "Super-Gluu-Push. Failed to send push notification :" % exception_value return 0 def sendPushNotificationImpl(self, user, app_id, super_gluu_request): if not self.pushNotificationsEnabled: print "Super-Gluu-Push. Push notifications are disabled" return None user_name = user.getUserId() print "Super-Gluu-Push. Sending push notification to user '%s' devices" % user_name userService = CdiUtil.bean(UserService) deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService) user_inum = userService.getUserInum(user_name) u2f_device_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, app_id, "oxId","oxDeviceData","oxDeviceNotificationConf") send_ios = 0 send_android = 0 if u2f_device_list.size() > 0: for u2f_device in u2f_device_list: print "Super-Gluu-Push. Send device notification to device" device_push_result = self.sendDevicePushNotification(user, app_id, u2f_device, super_gluu_request) send_ios += device_push_result["send_ios"] send_android += device_push_result["send_android"] else: print "Super-Gluu-Push. No device enrolled for user '%s'" % user_name return 0 msg = """Super-Gluu-Push. Send push notification. send_android: '%s', send_ios: '%s' """ print msg % (send_android, send_ios) return send_android + send_ios 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 sendApplePushNotification(self, pushNotificationContext): if self.pushSnsMode or self.pushGluuMode: if self.pushSnsMode: self.sendApplePushSnsNotification(pushNotificationContext) elif self.pushGluuMode: self.sendApplePushGluuNotification(pushNotificationContext) else: self.sendApplePushNativeNotification(pushNotificationContext) def sendAndroidPushNotification(self, pushNotificationContext): if self.pushSnsMode or self.pushGluuMode: if self.pushSnsMode: self.sendAndroidPushSnsNotification(pushNotificationContext) elif self.pushGluuMode: self.sendAndroidPushGluuNotification(pushNotificationContext) else: self.sendAndroidPushNativeNotification(pushNotificationContext) def sendApplePushSnsNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled apple_push_platform = PushPlatform.APNS targetEndpointArn = self.getTargetEndpointArn(apple_push_platform,pushNotificationContext) if targetEndpointArn == None: return None push_message = self.buildApplePushMessage(pushNotificationContext) apple_push_platform = PushPlatform.APNS if not self.pushAppleServiceProduction: apple_push_platform = PushPlatform.APNS_SANDBOX pushSnsService = pushNotificationContext.pushSnsService send_notification_result = pushSnsService.sendPushMessage(self.pushAppleService, apple_push_platform, targetEndpointArn, push_message, None) if debug: dbg_msg = """Super-Gluu-Push. Send iOS SNS push notification. message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_message, send_notification_result) def sendAndroidPushSnsNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled android_push_platform = PushPlatform.GCM targetEndpointArn = self.getTargetEndpointArn(android_push_platform, pushNotificationContext) if targetEndpointArn == None: return None pushSnsService = pushNotificationContext.pushSnsService push_message = self.buildAndroidPushMessage(pushNotificationContext) send_notification_result = pushSnsService.sendPushMessage(self.pushAndroidService, android_push_platform, targetEndpointArn, push_message, None) if debug: dbg_msg = """Super-Gluu-Push. Send Android SNS push notification. message:'%s', send_notification_result: '%s'""" print dbg_msg % (push_message, send_notification_result) def sendApplePushGluuNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled apple_push_platform = PushPlatform.APNS targetEndpointArn = self.getTargetEndpointArn(apple_push_platform, pushNotificationContext) if targetEndpointArn == None: return None push_message = self.buildApplePushMessage(pushNotificationContext) print "push message : %s" % push_message send_notification_result = self.pushAppleService.sendNotification(self.pushAppleServiceAuth, targetEndpointArn, push_message) print "push message sent" if debug: dbg_msg = """Super-Gluu-Push. Send iOS gluu push notification. message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_message, send_notification_result) def sendAndroidPushGluuNotification(self, pushNotificationContext): debug = pushNotificationContext.debugEnabled android_push_platform = PushPlatform.GCM targetEndpointArn = self.getTargetEndpointArn(android_push_platform, pushNotificationContext) if targetEndpointArn == None: return None push_message = self.buildAndroidPushMessage(pushNotificationContext) send_notification_result = self.pushAndroidService.sendNotification(self.pushAndroidServiceAuth, targetEndpointArn, push_message) if debug: dbg_msg = """Super-Gluu-Push. Send Android gluu push notification. message: '%s', send_notification_result: '%s' """ print dbg_msg % (push_message,send_notification_result) pass def sendApplePushNativeNotification(self, pushNotificationContext): title = self.titleTemplate message = self.messageTemplate % pushNotificationContext.appId push_token = pushNotificationContext.pushToken additional_fields = {"request": pushNotificationContext.superGluuRequest} debug = pushNotificationContext.debugEnabled msgBuilder = APNS.newPayload().alertBody(message).alertTitle(title).sound("default") msgBuilder.forNewsstand() msgBuilder.customFields(additional_fields) push_message = msgBuilder.build() send_notification_result = self.pushAppleService.push(push_token, push_message) if debug: dbg_msg = """Super-Gluu-Push. Send iOS native push notification. push_token:'%s', message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_token, push_message, send_notification_result) def sendAndroidPushNativeNotification(self, pushNotificationContext): title = self.titleTemplate superGluuRequest = pushNotificationContext.superGluuRequest msgBuilder = Message.Builder().addData("message", superGluuRequest).addData("title",title).collapseKey("single").contentAvailable(True) push_message = msgBuilder.build() push_token = pushNotificationContext.pushToken send_notification_result = self.pushAndroidService.send(push_message, push_token, 3) if pushNotificationContext.debugEnabled: dbg_msg = """Super-Gluu-Push. Send iOS native push notification. push_token:'%s', message: '%s', send_notification_result: '%s'""" print dbg_msg % (push_token, push_message, send_notification_result) def buildApplePushMessage(self, pushNotificationContext): title = self.titleTemplate message = self.messageTemplate % pushNotificationContext.appId sns_push_request_dictionary = { "request": pushNotificationContext.superGluuRequest, "aps": { "badge": 0, "alert": {"body":message,"title":title}, "category": "ACTIONABLE", "content-available": "1", "sound": "default" } } return json.dumps(sns_push_request_dictionary,separators=(',',':')) def buildAndroidPushMessage(self, pushNotificationContext): sns_push_request_dictionary = { "collapse_key": "single", "content_available": True, "time_to_live": 60, "data": { "message": pushNotificationContext.superGluuRequest, "title": self.titleTemplate } } return json.dumps(sns_push_request_dictionary,separators=(',',':')) 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