Source code for cityiq.token

# -*- coding: utf-8 -*-
# Copyright (c) 2019 Civic Knowledge. This file is licensed under the terms of the
# MIT License, included in this distribution as LICENSE
"""

"""

import base64
import json
import logging
from binascii import crc32
from pathlib import Path
from time import time
from requests import HTTPError
from .exceptions import AuthenticationError

import requests

logger = logging.getLogger(__name__)


[docs]def get_cached_token(cache_path, uaa, client, secret): """ Return a cached access token from the CityIQ service. Returns just the token. Use _get_token() to get the full response :param cache_path: Directory where cached token will be stored, if a directory or token name if a file :param uaa: Url to the user authentication service :param client: :param secret: :return: A token string If a directory is specified in cache_dir, the file name will be 'cityiq-token-<crc>.json', with the CRC32 of the source url. The token will be expired after 8 hours. """ EXPIRE_TIME = (8 * 60 * 60) token_path = Path(cache_path) if token_path.is_dir(): token_path = token_path.joinpath('cityiq-token-{:X}.json'.format(crc32(str(uaa).encode('ascii')))) # Expire the token try: if token_path.exists() and token_path.stat().st_ctime + EXPIRE_TIME < time(): logger.debug('token: expired; deleting') token_path.unlink() except FileNotFoundError: # This can happen in a concurrency case, where another process has changed the token pass if token_path.exists(): logger.debug('token: exists') with token_path.open() as f: response_text = f.read() data = json.loads(response_text) else: logger.debug('token: fetching') data = _get_token(uaa, client, secret) with token_path.open('w') as f: f.write(json.dumps(data)) return data['access_token']
[docs]def get_token(uaa, client, secret): """ Get an access token from the CityIQ service. Returns just the token. Use _get_token() to get the full response :param uaa: Url to the user authentication service :param client: :param secret: :return: """ return _get_token(uaa, client, secret)['access_token']
def _get_token(uaa, client, secret): """ Get an access token from the CityIQ service. Returns the full JSON response :param uaa: Url to the user authentication service :param client: :param secret: :return: """ uaa += '/oauth/token' cs = (client + ':' + secret).encode('ascii') credentials = base64.b64encode(cs) headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'Cache-Control': 'no-cache', 'Authorization': b'Basic ' + credentials } params = { 'client_id': client, 'grant_type': 'client_credentials' } response = requests.post(uaa, headers=headers, data=params) try: response.raise_for_status() except HTTPError as e: if e.response.status_code == 401: raise AuthenticationError() from e else: raise return response.json()