Skip to content

Commit

Permalink
Merge pull request #1418 from CastagnaIT/msl_profiles_fix_Leia
Browse files Browse the repository at this point in the history
[LEIA][Backport] Fix MSL user authentication
  • Loading branch information
CastagnaIT authored Sep 26, 2022
2 parents 2cedd8b + 1c75b7f commit fac4fc7
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 25 deletions.
51 changes: 30 additions & 21 deletions resources/lib/services/msl/msl_request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import random
import time

from resources.lib.globals import G
import resources.lib.common as common
from resources.lib.common.exceptions import MSLError
from resources.lib.globals import G
from resources.lib.services.msl.msl_utils import MSL_AUTH_USER_ID_TOKEN, MSL_AUTH_EMAIL_PASSWORD, MSL_AUTH_NETFLIXID
from resources.lib.utils.logging import measure_exec_time_decorator


Expand Down Expand Up @@ -126,14 +128,16 @@ def decrypt_header_data(self, data, enveloped=True):

def _add_auth_info(self, header_data, auth_data):
"""User authentication identifies the application user associated with a message"""
# Warning: the user id token contains also contains the identity of the netflix profile
# therefore it is necessary to use the right user id token for the request
if auth_data.get('user_id_token'):
if auth_data['auth_scheme'] == MSL_AUTH_USER_ID_TOKEN:
# Authentication scheme with: User ID token
# Make requests by using by default main netflix profile, since the user id token contains also the identity
# of the netflix profile, to send data to the right profile (e.g. for continue watching) must be used
# SWITCH_PROFILE scheme to switching MSL profile.
# 25/09/2022: SWITCH_PROFILE auth scheme has been disabled on netflix website backend and not works anymore.
if auth_data['use_switch_profile']:
# The SWITCH_PROFILE is a custom Netflix MSL user authentication scheme
# that is needed for switching profile on MSL side
# works only combined with user id token and can not be used with all endpoints
# after use it you will get user id token of the profile specified in the response
# The SWITCH_PROFILE is a custom Netflix MSL user authentication scheme, that is needed for switching
# profile on MSL side, works only combined with user id token and can not be used with all endpoints
# after use it you will get the user id token of the requested profile in the response.
header_data['userauthdata'] = {
'scheme': 'SWITCH_PROFILE',
'authdata': {
Expand All @@ -142,10 +146,10 @@ def _add_auth_info(self, header_data, auth_data):
}
}
else:
# Authentication with user ID token containing the user identity (netflix profile)
header_data['useridtoken'] = auth_data['user_id_token']
else:
# Authentication with the user credentials
elif auth_data['auth_scheme'] == MSL_AUTH_EMAIL_PASSWORD:
# Authentication scheme with: Email password
# Make requests by using main netflix profile only (you cannot update continue watching to other profiles)
credentials = common.get_credentials()
header_data['userauthdata'] = {
'scheme': 'EMAIL_PASSWORD',
Expand All @@ -154,13 +158,18 @@ def _add_auth_info(self, header_data, auth_data):
'password': credentials['password']
}
}
# Authentication with user Netflix ID cookies
# This not works on android,
# will raise: User authentication data does not match entity identity
# header_data['userauthdata'] = {
# 'scheme': 'NETFLIXID',
# 'authdata': {
# 'netflixid': cookies['NetflixId'],
# 'securenetflixid': cookies['SecureNetflixId']
# }
# }
elif auth_data['auth_scheme'] == MSL_AUTH_NETFLIXID:
# Authentication scheme with: Netflix ID cookies
# Make requests by using the same netflix profile used/set on nfsession (website)

# Workaround to get updated auth data from nfsession
data = common.make_http_call('get_auth_data', {'placeholder_data': ''})
header_data['userauthdata'] = {
'scheme': 'NETFLIXID',
'authdata': {
'netflixid': data['NetflixId'],
'securenetflixid': data['SecureNetflixId']
}
}
else:
raise MSLError('Authentication scheme not supported.')
14 changes: 11 additions & 3 deletions resources/lib/services/msl/msl_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
from resources.lib.globals import G
from resources.lib.services.msl.msl_request_builder import MSLRequestBuilder
from resources.lib.services.msl.msl_utils import (display_error_info, generate_logblobs_params, ENDPOINTS,
MSL_DATA_FILENAME, create_req_params)
MSL_DATA_FILENAME, create_req_params, MSL_AUTH_NETFLIXID,
MSL_AUTH_USER_ID_TOKEN)
from resources.lib.services.tcp_keep_alive import enable_tcp_keep_alive
from resources.lib.utils.esn import get_esn
from resources.lib.utils.logging import LOG, measure_exec_time_decorator, perf_clock
Expand All @@ -32,6 +33,8 @@
class MSLRequests(MSLRequestBuilder):
"""Provides methods to make MSL requests"""

MSL_AUTH_SCHEME = MSL_AUTH_NETFLIXID

def __init__(self, msl_data=None):
super(MSLRequests, self).__init__()
from requests import session
Expand Down Expand Up @@ -162,12 +165,17 @@ def _check_user_id_token(self, disable_msl_switch, force_auth_credential=False):
def chunked_request(self, endpoint, request_data, esn, disable_msl_switch=True, force_auth_credential=False):
"""Do a POST request and process the chunked response"""
self._mastertoken_checks()
auth_data = self._check_user_id_token(disable_msl_switch, force_auth_credential)

auth_data = {'auth_scheme': self.MSL_AUTH_SCHEME}

if self.MSL_AUTH_SCHEME == MSL_AUTH_USER_ID_TOKEN:
auth_data = self._check_user_id_token(disable_msl_switch, force_auth_credential)

LOG.debug('Chunked request will be executed with auth data: {}', auth_data)

chunked_response = self._process_chunked_response(
self._post(endpoint, self.msl_request(request_data, esn, auth_data)),
save_uid_token_to_owner=auth_data['user_id_token'] is None)
save_uid_token_to_owner=auth_data.get('user_id_token') is None)
return chunked_response['result']

def _post(self, endpoint, request_data):
Expand Down
4 changes: 4 additions & 0 deletions resources/lib/services/msl/msl_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
'logblobs': CHROME_PLAYAPI_URL + 'logblob/1'
}

MSL_AUTH_NETFLIXID = 'NETFLIXID' # Netflix ID cookies user authentication
MSL_AUTH_EMAIL_PASSWORD = 'EMAIL_PASSWORD' # Email password user authentication
MSL_AUTH_USER_ID_TOKEN = 'USER_ID_TOKEN' # User ID token user authentication

MSL_DATA_FILENAME = 'msl_data.json'

EVENT_START = 'start' # events/start : Video starts
Expand Down
11 changes: 10 additions & 1 deletion resources/lib/services/nfsession/nfsession_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def __init__(self):
self.get_metadata,
self.update_loco_context,
self.update_videoid_bookmark,
self.get_loco_data
self.get_loco_data,
self.get_auth_data
]
# Share the activate profile function to SessionBase class
self.external_func_activate_profile = self.activate_profile
Expand Down Expand Up @@ -91,6 +92,14 @@ def fetch_initial_page(self):
self.session.cookies.clear()
self.login()

def get_auth_data(self, placeholder_data): # pylint: disable=unused-argument
"""Workaround to get auth data"""
data = {
'NetflixId': self.session.cookies['NetflixId'],
'SecureNetflixId': self.session.cookies['SecureNetflixId']
}
return data

@measure_exec_time_decorator(is_immediate=True)
def activate_profile(self, guid):
"""Set the profile identified by guid as active"""
Expand Down

0 comments on commit fac4fc7

Please sign in to comment.