[nebula] Clean up credentials-based authentication

This commit is contained in:
Henrik Heimbuerger 2020-10-23 05:43:55 +02:00
parent 8e3842e156
commit aeda0f3356
1 changed files with 35 additions and 16 deletions

View File

@ -15,12 +15,15 @@ class NebulaIE(InfoExtractor):
off-YouTube from a small hand-picked group of creators.
All videos require a subscription to watch. There are no known freely available videos. An authentication token to
an account with a valid subscription can be specified in multiple ways.
an account with a valid subscription can be specified in multiple ways, including credentials in .netrc or a cookie
jar.
As neither of these parameters appear to be supported by the unit test runner, it's recommended to set the envvar
NEBULA_TOKEN to execute the test runs.
Nebula uses the Zype video infrastructure and this extractor is using the 'url_transparent' mode to hand off
video extraction to the Zype extractor.
This description has been last updated on 2020-05-11.
This description has been last updated on 2020-10-22.
"""
_VALID_URL = r'https?://(?:www\.)?watchnebula\.com/videos/(?P<id>[-\w]+)' # the 'id' group is actually the display_id, but we misname it 'id' to be able to use _match_id()
@ -73,35 +76,44 @@ class NebulaIE(InfoExtractor):
def _perform_login(self, username, password, video_id):
"""
Perform login to Nebula.
Log in to Nebula, authenticating using a given username and password.
Takes a username (email address) and password. Returns a Nebula token.
Returns a Nebula token, as the frontend would store it in the
nebula-auth cookie. Or False, if authentication fails.
"""
data = json.dumps({'email': username, 'password': password}).encode('utf8')
request = sanitized_Request(method='POST',
url='https://api.watchnebula.com/api/v1/auth/login/',
data=data,
headers={'content-type': 'application/json'})
response = self._download_json(request, fatal=True, video_id=video_id,
note='Logging in to Nebula')
response = self._download_json(request, fatal=False, video_id=video_id,
note='Authenticating to Nebula with supplied credentials',
errnote='Authentication failed or rejected')
if not response or 'key' not in response:
return False
return response['key']
def _retrieve_nebula_auth(self, video_id):
"""
Attempt to find a Nebula API token. Makes multiple attempts in the following order:
a) the --video-password command line argument
Attempt to find a Nebula API token. Makes multiple attempts in the
following order:
a) login credentials used to authenticate to the Nebula login endpoint,
either from .netrc or specified using --username/--password
b) the --cookies supplied cookie jar
c) the NEBULA_TOKEN environment variable
If none of these are successful, an end user-intended error message is returned, listing some solutions.
# TODO: are these authentication methods, in this order, the best practice for youtube-dl?
d) the --video-password command line argument (this isn't documented in
the error message, because probably highly unpopular)
If none of these are successful, an end user-intended error message is
raised, listing some solutions.
"""
nebula_token = None
# option #1: login credentials via .netrc or --username and --password
username, password = self._get_login_info()
nebula_token = self._perform_login(username, password, video_id)
return nebula_token
if username and password:
nebula_token = self._perform_login(username, password, video_id)
nebula_token = self._downloader.params.get('videopassword')
# option #2: nebula token via cookie jar
if not nebula_token:
# TODO: is there a helper to do all this cookie extraction?
nebula_cookies = self._get_cookies('https://watchnebula.com')
@ -109,12 +121,19 @@ class NebulaIE(InfoExtractor):
if nebula_cookie:
nebula_cookie_value = compat_urllib_parse_unquote(nebula_cookie.value)
nebula_token = self._parse_json(nebula_cookie_value, video_id).get('apiToken')
# option #3: nebula token via environment variable
if not nebula_token and 'NEBULA_TOKEN' in os.environ:
nebula_token = os.environ.get('NEBULA_TOKEN')
# option #4: nebula token via --videopassword
if not nebula_token:
nebula_token = self._downloader.params.get('videopassword')
if not nebula_token:
raise ExtractorError('Nebula requires an account with an active subscription. '
'You can supply a corresponding token by either '
'a) finding your nebula-auth cookie and then specifying it via --video-password, or '
'You can supply your authentication information by either '
'a) storing your credentials in .netrc or supplying them via --username and --password, or '
'b) passing in a cookie jar containing a nebula-auth cookie via --cookies, or '
'c) setting the environment variable NEBULA_TOKEN.')
return nebula_token