Skip to content

Commit

Permalink
Auth improvements (#253)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelarnauts committed Jan 7, 2021
1 parent 85c234a commit 9b67091
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 40 deletions.
4 changes: 2 additions & 2 deletions resources/lib/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
from resources.lib import kodilogging, kodiutils
from resources.lib.vtmgo.exceptions import InvalidLoginException, LoginErrorException

kodilogging.config()
routing = routing.Plugin() # pylint: disable=invalid-name

_LOGGER = logging.getLogger('plugin')
_LOGGER = logging.getLogger(__name__)


@routing.route('/')
Expand Down Expand Up @@ -315,4 +314,5 @@ def iptv_epg():

def run(params):
""" Run the routing plugin """
kodilogging.config()
routing.run(params)
2 changes: 1 addition & 1 deletion resources/lib/modules/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def show_mainmenu(self):
""" Show the main menu """
listing = []

account = self._auth.login()
account = self._auth.get_tokens()

listing.append(kodiutils.TitleItem(
title=kodiutils.localize(30007), # TV Channels
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/modules/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from resources.lib import kodiutils
from resources.lib.kodiplayer import KodiPlayer
from resources.lib.vtmgo.exceptions import UnavailableException, StreamGeoblockedException, StreamUnavailableException
from resources.lib.vtmgo.exceptions import StreamGeoblockedException, StreamUnavailableException, UnavailableException
from resources.lib.vtmgo.vtmgo import VtmGo
from resources.lib.vtmgo.vtmgoauth import VtmGoAuth
from resources.lib.vtmgo.vtmgostream import VtmGoStream
Expand Down
4 changes: 2 additions & 2 deletions resources/lib/modules/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
from SocketServer import TCPServer

try: # Python 3
from urllib.parse import urlparse, parse_qs
from urllib.parse import parse_qs, urlparse
except ImportError: # Python 2
from urlparse import urlparse, parse_qs
from urlparse import parse_qs, urlparse

_LOGGER = logging.getLogger(__name__)

Expand Down
4 changes: 2 additions & 2 deletions resources/lib/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
from resources.lib.modules.proxy import Proxy
from resources.lib.vtmgo.exceptions import NoLoginException

kodilogging.config()
_LOGGER = logging.getLogger('service')
_LOGGER = logging.getLogger(__name__)


class BackgroundService(Monitor):
Expand Down Expand Up @@ -188,4 +187,5 @@ def __get_subtitle_paths():

def run():
""" Run the BackgroundService """
kodilogging.config()
BackgroundService().run()
2 changes: 1 addition & 1 deletion resources/lib/vtmgo/vtmgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class VtmGo:
def __init__(self, auth):
""" Initialise object """
self._auth = auth
self._tokens = self._auth.login()
self._tokens = self._auth.get_tokens()

def _mode(self):
""" Return the mode that should be used for API calls """
Expand Down
66 changes: 37 additions & 29 deletions resources/lib/vtmgo/vtmgoauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from hashlib import md5
from uuid import uuid4

from resources.lib import kodiutils
from requests import HTTPError

from resources.lib.vtmgo import API_ENDPOINT, Profile, util
from resources.lib.vtmgo.exceptions import InvalidLoginException, LoginErrorException, NoLoginException

Expand Down Expand Up @@ -89,14 +90,18 @@ def __init__(self, username, password, loginprovider, profile, token_path):
except (IndexError, AttributeError):
self._account.product = None

def check_credentials_change(self):
""" Check if credentials have changed """
def _check_credentials_change(self):
""" Check if credentials have changed.
:return: The hash of the current credentials.
:rtype: str
"""
old_hash = self._account.hash
new_hash = md5((self._username + ':' + self._password + ':' + self._loginprovider).encode('utf-8')).hexdigest()

if new_hash != old_hash:
_LOGGER.debug('Credentials have changed, clearing tokens.')
self._account.hash = new_hash
self.logout()
return new_hash
return None

def get_profiles(self, products='VTM_GO,VTM_GO_KIDS'):
""" Returns the available profiles """
Expand Down Expand Up @@ -127,39 +132,52 @@ def login(self, force=False):
:rtype: AccountStorage
"""
# Check if credentials have changed
self.check_credentials_change()
new_hash = self._check_credentials_change()
if new_hash:
_LOGGER.debug('Credentials have changed, forcing a new login.')
self._account.hash = new_hash
force = True

# Use cached token if it is still valid
if force or not self._account.is_valid_token():
# Do actual login
self._web_login()

return self._account

def logout(self):
""" Clear the session tokens. """
self._account.jwt_token = None
self._save_cache()

def get_tokens(self):
""" Return the tokens.
:return:
:rtype: AccountStorage
"""
return self._account

def _web_login(self):
""" Executes a login and returns the JSON Web Token.
:rtype str
"""

# Yes, we have accepted the cookies
util.SESSION.cookies.clear()
util.SESSION.cookies.set('authId', str(uuid4()))

# Start login flow
response = util.http_get('https://vtm.be/vtmgo/aanmelden?redirectUrl=https://vtm.be/vtmgo')
response.raise_for_status()
util.http_get('https://vtm.be/vtmgo/aanmelden?redirectUrl=https://vtm.be/vtmgo')

# Send login credentials
response = util.http_post('https://login2.vtm.be/login?client_id=vtm-go-web', form={
'userName': kodiutils.get_setting('username'),
'password': kodiutils.get_setting('password'),
'jsEnabled': 'true',
})
response.raise_for_status()
try:
response = util.http_post('https://login2.vtm.be/login?client_id=vtm-go-web', form={
'userName': self._username,
'password': self._password,
'jsEnabled': 'true',
})
except HTTPError as exc:
if exc.response.status_code == 400:
raise InvalidLoginException()
raise

if 'errorBlock-OIDC-004' in response.text: # E-mailadres is niet gekend.
raise InvalidLoginException()
Expand All @@ -172,7 +190,6 @@ def _web_login(self):

# Follow login
response = util.http_get('https://login2.vtm.be/authorize/continue?client_id=vtm-go-web')
response.raise_for_status()

# Extract state and code
matches_state = re.search(r'name="state" value="([^"]+)', response.text)
Expand All @@ -188,11 +205,10 @@ def _web_login(self):
raise LoginErrorException(code=101) # Could not extract authentication code

# Okay, final stage. We now need to POST our state and code to get a valid JWT.
response = util.http_post('https://vtm.be/vtmgo/login-callback', form={
util.http_post('https://vtm.be/vtmgo/login-callback', form={
'state': state,
'code': code,
})
response.raise_for_status()

# Get JWT from cookies
self._account.jwt_token = util.SESSION.cookies.get('lfvp_auth')
Expand All @@ -216,11 +232,3 @@ def _save_cache(self):

with open(os.path.join(self._token_path, self.TOKEN_FILE), 'w') as fdesc:
json.dump(self._account.__dict__, fdesc, indent=2)

def clear_token(self):
""" Remove the cached JWT. """
_LOGGER.debug('Clearing token cache')
path = os.path.join(self._token_path, self.TOKEN_FILE)
if kodiutils.exists(path):
kodiutils.delete(path)
self._account = AccountStorage()
2 changes: 1 addition & 1 deletion resources/lib/vtmgo/vtmgostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self):
'VTM',
kodiutils.get_setting('profile'),
kodiutils.get_tokens_path())
self._tokens = self._auth.login()
self._tokens = self._auth.get_tokens()

def _mode(self):
""" Return the mode that should be used for API calls """
Expand Down
2 changes: 1 addition & 1 deletion tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def setUpClass(cls):
kodiutils.get_tokens_path())

def test_login(self):
token = self._vtmgoauth.login()
token = self._vtmgoauth.get_tokens()
self.assertTrue(token)

def test_get_profiles(self):
Expand Down

0 comments on commit 9b67091

Please sign in to comment.