Skip to main content

Token Reuse

To call the Data Portal API, you have to authenticate your requests with an access token. To get your access token call the /auth/login/ endpoint and this token will be valid for 24 hours. We recommend to always adapt your code for token reuse. i.e. instead of requesting a new token every time you run a script, keep using just one token until it has expired.

There are several reasons to do this:

Requesting a new token is a slow process. You can make your scripts work much faster by adopting token reuse

Token requests are potentially risky. User credentials and access tokens are highly sensitive data. Every time you send or receive them over the internet, you give potential attackers a chance to acquire sensitive data

Data portal API is rate limited. Also each unnecessary API call wastes your request budget

Requesting too many tokens may be treated as suspicious behavior. The Authentication server may block your IP

How to Reuse Tokens in Python Scripts

The expiresIn field in the response of /auth/login endpoint will tell you the time when the token expires.

>>> import requests
>>> response = requests.post ( # requesting an access token
'https://lolesports-api.bayesesports.com/v2/auth/login',
json={'username': 'my_username', 'password': 'my_password'},
headers={"Content-Type": "application/json"} )
>>> token = response.json()['accessToken'] # parsing out the token from response
>>> expires_in = response.json()['expiresIn'] # 86400

expiresIn holds the number of seconds until the token is expired. In Python, use the timedelta class to determine the expiration date:

>>> from datetime import datetime, timedelta
>>> expire_date = datetime.now() + timedelta(seconds=expires_in)
>>> print(expire_date)

2022-02-23 11:53:32.846107

Store the expiration date and the access token in a local JSON file to reuse it on the next run:

>>> import json
>>> with open('token.json', 'w') as f:
json.dump({'token': token, 'expires': expire_date.timestamp()}, f)

When you later open the Python interpreter again, load the token and check if it is still valid:

>>> from datetime import datetime
>>> import json
>>> with open('token.json') as f:
data = json.load(f)

>>> expire_date = datetime.fromtimestamp(data['expires'])
>>> token_valid = expire_date > datetime.now()
>>> token_valid

True

Complete example

Use this approach to create a module that will handle token reuse for us. This module will be suitable for simple scripts. For advanced apps, you have to come up with more stable and secure solution. Check our recommendations at the end of this page.

First, let's write the login function that will send the /auth/login request:

import requests

def portal_login(username: str, password: str) -> dict:
url = 'https://lolesports-api.bayesesports.com/v2/auth/login'
headers = {"Content-Type": "application/json"}
creds = {'username': username, 'password': password}
response = requests.post(url, json=creds, headers=headers)
if response.status_code == 200:
return response.json()
else:
response.raise_for_status()

The portal_login function takes user credentials as input, requests the access token by calling API which returns the JSON dict from the server. This JSON dict will contain the access token, its lifetime in seconds, and the refresh token.

Next, we'll write a function that will store these details in a local JSON file:

import json
import os
from datetime import datetime
from datetime import timedelta

def store_token(response_token: dict, filename: str):
result = dict(response_token) # create a copy of the input dict
expire_date = datetime.now() + timedelta(seconds=result.pop('expiresIn'))
result['expiresAt'] = expire_date.timestamp()
with open(filename, 'w') as f:
json.dump(result, f)

Note that we are replacing the expiresIn field, which holds token lifetime in seconds, with a new expiresAt field, that will hold a UNIX timestamp of when the token expires. Otherwise, we won't be able to check the token freshness later on.

Talking about freshness, it's a good point to write a function that will check exactly that:

def is_stored_token_fresh(stored_token: dict) -> bool:
expire_date = datetime.fromtimestamp(stored_token['expiresAt'])
return datetime.now() < expire_date

The idea of is_stored_token_fresh function is very simple: we compare the expiration timestamp, stored in the JSON file, with current date. If the expiration date is in the future, then the token is still fresh.

But this function takes a dictionary as the input. We still have to load it from the JSON file. Let's do that:

def get_token_from_file(filename: str):
if not os.path.exists(filename):
return None
with open(filename) as f:
stored_token = json.load(f)
if is_stored_token_fresh(stored_token):
return stored_token['accessToken']
else:
return None

If the file does not exist yet, or if the token is already expired, the function will return None. This way the caller of this function can determine if requesting a new token is required.

📝 Note

This approach is fine for simple scripts, but for advanced applications a more preferable way would be to raise a custom error if the token is expired, and then catch it in the caller of this function.

All is left to do is to write the main function that will either load the token from the file, or request a new one from the API.

from getpass import getpass

def get_token() -> str:
filename = 'token.json'
token = get_token_from_file(filename)
if token is None:
# stored token is expired, asking user for credentials
username = input(f'Portal login: ')
password = getpass(f'Password for {username}: ')
# requesting a new token from API
response_token = portal_login(username, password)
# storing the token details
store_token(response_token, filename)
token = response_token['accessToken']
return token

Now you can get your token by simply calling get_token:

>>> token = get_token()

Here's the full module in case you want to use it in your scripts:

get_token.py
import os
import requests
import json
from typing import Optional
from datetime import datetime
from datetime import timedelta
from getpass import getpass

TOKEN_FILE = 'token.json'
PWD_ENV = 'PORTAL_PASSWORD'
USRN_ENV = 'PORTAL_LOGIN'

def portal_login(username: str, password: str) -> dict:
'''Send API request to get an access token using supplied `username` and `password`. Return JSON response, received from the server'''
url = 'https://lolesports-api.bayesesports.com/v2/auth/login'
headers = {"Content-Type": "application/json"}
creds = {'username': username, 'password': password}
response = requests.post(url, json=creds, headers=headers)
if response.status_code == 200:
return response.json()
else:
response.raise_for_status()

def store_token(response_token: dict, filename: str):
'''Save access token details, received from the API to a JSON file. The expiresIn field is replaced with expiresAt UNIX timestamp'''
result = dict(response_token)
expire_date = datetime.now() + timedelta(seconds=result.pop('expiresIn'))
result['expiresAt'] = expire_date.timestamp()
with open(filename, 'w') as f:
json.dump(result, f)

def is_stored_token_fresh(stored_token: dict) -> bool:
'''Check if the access token that is stored in filename is still valid'''
expire_date = datetime.fromtimestamp(stored_token['expiresAt'])
return datetime.now() < expire_date

def get_token_from_file(filename) -> Optional[str]:
'''Load access token info from JSON `filename` and return the access token if it is still fresh. If it's not, or if the file is missing, return None'''
if not os.path.exists(filename):
return None
with open(filename) as f:
stored_token = json.load(f)
if is_stored_token_fresh(stored_token):
return stored_token['accessToken']
else:
return None

def get_token() -> str:
'''Get an auth token from the local file or send an API request to login if stored token is too old'''
token = get_token_from_file(TOKEN_FILE)
if token is None:
username = os.environ.get(USRN_ENV) or input(f'Portal login: ')
password = os.environ.get(PWD_ENV) or getpass(f'Password for {username}: ')
response_token = portal_login(username, password)
store_token(response_token, TOKEN_FILE)
token = response_token['accessToken']
return token

if __name__ == '__main__':
print(get_token())

Token Reuse in Applications

The above approach is suitable only for simple local scripts. If you are building an application that uses Data Portal API, you should probably add more complex token handling.

Namely, your application should:

  • Keep track of different users' access tokens and their expiration time
  • Provide a secure, local storage for this info. Depending on the kind of application: a file, a cookie, a database, or something else. The access token can be regarded as an identification credential (like username & password), the only difference being the token will expire at some point in time. It should be stored in a secure manner to prevent leakage.
  • Request a new access token only when the previous one expires
  • Use /auth/refresh instead of /auth/login for repeated token requests
  • Handle refresh token expiration (they live for 30 days, but expire in 15 days of inactivity)

And always remember that access tokens are sensitive data and should be treated with the same care as any other credentials.