import time from typing import Dict import requests from flask import current_app, session class Auth0: TOKEN_KEY = 'auth0_api_session_token' EXPIRE_AT = 'expire_at' cache = {} @classmethod def _execute_request( cls, url: str, headers: dict or None = None, json_body: dict or None = None, data: dict or None = None, files: dict or None = None, method: str = 'GET', is_auth: bool = False ) -> dict or None: if not headers: headers = {} if not is_auth: headers.update({'Authorization': 'Bearer {}'.format(cls.get_token())}) # make http request and retry on rate limits retry_count = 0 while True: response = requests.request( method=method, url=url, json=json_body, data=data, headers=headers, files=files ) if response.status_code == 200 or retry_count >= 5: break retry_count += 1 time.sleep(retry_count * 5) # handle non 2xx statuses if not response: raise ValueError('Incorrect request result') if response.text: response_data = response.json() return response_data return None @classmethod def get_token(cls) -> str: """Get auth0 management API bearer token. Returns: str: Bearer token. """ current_time = time.time() if cls.TOKEN_KEY not in session or session.get(cls.EXPIRE_AT, current_time) < current_time - 60: url = 'https://{}/oauth/token'.format(current_app.config['AUTH0_DOMAIN']) body = { 'client_id': current_app.config['AUTH0_MANAGEMENT_CLIENT_ID'], 'client_secret': current_app.config['AUTH0_MANAGEMENT_CLIENT_SECRET'], 'audience': 'https://{}/api/v2/'.format(current_app.config['AUTH0_DOMAIN']), 'grant_type': 'client_credentials' } token_data = cls._execute_request(url=url, data=body, method='POST', is_auth=True) session[cls.TOKEN_KEY] = token_data['access_token'] session[cls.EXPIRE_AT] = current_time + token_data['expires_in'] return session[cls.TOKEN_KEY] @classmethod def get_user(cls, user_id: str) -> Dict[str, dict]: url = 'https://{}/api/v2/users/{}'.format(current_app.config['AUTH0_DOMAIN'], user_id) if url not in cls.cache: cls.cache[url] = cls._execute_request(url) return cls.cache[url]