async def process_token_refresh_request(request_context, client_single_request, server_single_response, async_splunk_client, encryption_context): if not isinstance(request_context.auth_header, JWTAuthHeader): secured_session_token = encryption_context.secure_session_token( request_context.auth_header.session_token) server_single_response.tokenRefreshResponse.sessionToken = secured_session_token server_single_response.tokenRefreshResponse.tokenExpiresAt = 0 server_single_response.tokenRefreshResponse.code = request_pb2.TokenRefreshResponse.SUCCESS return session_token = request_context.auth_header.token valid_request = await async_is_valid_session_token( request_context.current_user, session_token, async_splunk_client) if not valid_request: server_single_response.tokenRefreshResponse.code = request_pb2.TokenRefreshResponse.ERROR_TOKEN_INVALID return old_token_info = calculate_token_info(session_token) new_JWT = await async_splunk_client.async_create_new_JWT_token( request_context.current_user, request_context.auth_header) if new_JWT.code not in {HTTPStatus.CREATED, HTTPStatus.OK}: error = await new_JWT.text() LOGGER.warning( "Failed to create new token status_code={}, error={}".format( new_JWT.code, error)) server_single_response.tokenRefreshResponse.code = request_pb2.TokenRefreshResponse.ERROR_CREATING_TOKEN return new_JWT_json = await new_JWT.json() new_jwt_credentials = SplunkJWTCredentials(request_context.current_user) new_jwt_credentials.token = new_JWT_json['entry'][0]['content']['token'] # Get token expiry new_token_info = calculate_token_info(new_jwt_credentials.token) server_single_response.tokenRefreshResponse.tokenExpiresAt = new_token_info[ 'exp'] # Encrypt this token new_session_token = new_jwt_credentials.get_credentials( ) if sys.version_info < (3, 0) else str.encode( new_jwt_credentials.get_credentials()) encrypted_token = encryption_context.secure_session_token( new_session_token) server_single_response.tokenRefreshResponse.sessionToken = encrypted_token server_single_response.tokenRefreshResponse.code = request_pb2.TokenRefreshResponse.SUCCESS
def sync(self): """ Gets all registered users. Gets all tokens per user, sorted by expiry date. Deletes all tokens except the one with the most recent expiration date and any that are being used as subscription credentials. """ all_registered_users = get_all_mobile_users(self.session_key) try: for user in all_registered_users: tokens = get_all_secure_gateway_tokens(self.session_key, user) current_time = get_current_timestamp() index_to_delete = min(3, len(tokens)) for i in range(0, index_to_delete - 1): if token[i]['content']['claims']['exp'] < current_time: index_to_delete = i break tokens_to_delete = tokens[index_to_delete:] kvstore_subscription_credentials = KvStore( constants.SUBSCRIPTION_CREDENTIALS_COLLECTION_NAME, self.session_key, owner=user) response, credentials = kvstore_subscription_credentials.get_all_items( ) credentials = json.loads(credentials) jwt_credential = [ c for c in credentials if 'session_type' in c and c['session_type'] == constants.JWT_TOKEN_TYPE[0] ] if jwt_credential: subscription_token_info = calculate_token_info( jwt_credential['session_key']) else: subscription_token_info = None for token in tokens_to_delete: # if that token does not exist in subscription credentials if not subscription_token_info or token[ 'name'] != subscription_token_info['id']: delete_token_by_id(self.session_key, user, token['name']) except: LOGGER.exception("Exception performing DeleteTokensSync")
def get_expiration(self): return calculate_token_info(self.token)['exp']
async def handle_mdm_authentication_request(mdm_auth_request_proto, encryption_context, server_context, logger, config, request_id): """ Takes a MDM Auth Request proto, decrypts the encrypted credentials bundle, validates the credentials, persists device information to the server and sends cloudgateway a confirmation result message Args: mdm_auth_request_proto (MdmAuthenticationRequest proto): request from the client to perform MDM registration encryption_context (EncryptionContext): server_context (ServerContext): object which specifies how mdm registration should be validated and how credentials should be persisted to the server logger (Logger): logger class to handle logging Returns: """ logger.info( "Parsing MDM Authentication Request, request_id={}".format(request_id)) client_credentials = sb_common_pb2.MdmAuthenticationRequest.ClientCredentials( ) client_credentials.ParseFromString( mdm_auth_request_proto.clientCredentials) mdm_signature = mdm_auth_request_proto.mdmSignature client_signature = mdm_auth_request_proto.clientSignature try: logger.debug( "Validating MDM signature MDM request message, request_id={}". format(request_id)) mdm_signing_key = await server_context.get_mdm_signing_key() if not sign_verify(encryption_context.sodium_client, mdm_signing_key, mdm_auth_request_proto.clientCredentials, mdm_signature): raise CloudgatewayMdmRegistrationError( CloudgatewayMdmRegistrationError.errortype.unknown_error, "mdm signature validation failed") logger.debug( "Validating registration version={}, request_id={}".format( client_credentials.registrationVersion, request_id)) if client_credentials.registrationVersion != MDM_REGISTRATION_VERSION: raise CloudgatewayMdmRegistrationError( CloudgatewayMdmRegistrationError.ErrorType.UNKNOWN_ERROR, "Incompatible Mdm Registration Version. Expected={}".format( MDM_REGISTRATION_VERSION)) encrypted_credentials_bundle = client_credentials.encryptedCredentialsBundle credentials_bundle = mdm.parse_mdm_encrypted_credentials_bundle( encrypted_credentials_bundle, encryption_context) client_id = credentials_bundle.registeringAppId username = credentials_bundle.username password = credentials_bundle.password encrypt_public_key = credentials_bundle.publicKeyForEncryption sign_public_key = credentials_bundle.publicKeyForSigning login_type = credentials_bundle.loginType user_session_token = credentials_bundle.sessionToken # JWT session token sent by the client after MDM SAML friendly_name = credentials_bundle.registeringAppFriendlyName platform = credentials_bundle.registeringAppPlatform logger.debug( "Validating publicKey signature of MDM request message, request_id={}" .format(request_id)) if not sign_verify(encryption_context.sodium_client, sign_public_key, mdm_auth_request_proto.clientCredentials, client_signature): raise CloudgatewayMdmRegistrationError( CloudgatewayMdmRegistrationError.ErrorType.UNKNOWN_ERROR, "client signature validation failed") device_info = DeviceInfo(encrypt_public_key, sign_public_key, device_id=make_device_id( encryption_context, sign_public_key), app_id=client_id, client_version="", app_name=friendly_name, platform=platform) if login_type == constants.SAML: encrypted_session_token = user_session_token raw_token = base64.b64decode(encrypted_session_token) decrypted_session_token = decrypt_session_token( encryption_context.sodium_client, raw_token, encryption_context.encrypt_public_key(), encryption_context.encrypt_private_key()) session_jsn = json.loads(decrypted_session_token) token_type = http_pb2.TokenType.Value('JWT') token_expires_at = calculate_token_info( session_jsn['token'])['exp'] else: await server_context.validate(username, password, device_info) logger.debug( "Server validated mdm registration request. request_id={}". format(request_id)) session_token = await server_context.create_session_token( username, password) encrypted_session_token = encryption_context.secure_session_token( session_token) token_type = http_pb2.TokenType.Value('SESSION') token_expires_at = 0 server_version = await server_context.get_server_version() logger.debug("Server returned server_version={}, request_id={}".format( server_version, request_id)) deployment_name = await server_context.get_deployment_name() logger.debug( "Server returned deployment_name={}, request_id={}".format( deployment_name, request_id)) server_type_id = await server_context.get_server_type() env_metadata = await server_context.get_environment_meta( device_info, username) pairing_info = mdm.build_pairing_info(encrypted_session_token, credentials_bundle.username, server_version, deployment_name, server_type_id, token_type, token_expires_at, env_metadata=env_metadata) confirmation_result = mdm.build_successful_confirmation_result( pairing_info) await server_context.persist_device_info(device_info, username) logger.info( "Successfully persisted device registration information, request_id={}" .format(request_id)) except CloudgatewayMdmRegistrationError as e: logger.exception( "MDM registration error occurred={}, request_id={}".format( e, request_id)) confirmation_result = mdm.build_error_confirmation_result(e.to_proto()) except Exception as e: logger.exception( "Unexpected error occurred during MDM registration={}, request_id={}" .format(e, request_id)) error = http_pb2.HttpError() error.code = http_pb2.HttpError.ERROR_UNKNOWN error.message = str(e) confirmation_result = mdm.build_error_confirmation_result(error) mdm_authentication_confirmation_request = mdm.build_mdm_authentication_confirmation_request( confirmation_result, encryption_context, device_info) r = await mdm.async_send_confirmation_result( mdm_authentication_confirmation_request, encryption_context, server_context.async_spacebridge_client) resp = await r.text() logger.info( "Completed MDM Authentication Request with response={}, code={}, request_id={}" .format(resp, r.code, request_id)) return mdm_authentication_confirmation_request