Package oauth2client :: Module clientsecrets |
[hide private]
[frames] | no frames]

# Source Code for Module oauth2client.clientsecrets

      1  # Copyright (C) 2011 Google Inc.
      2  #
      3  # Licensed under the Apache License, Version 2.0 (the "License");
      4  # you may not use this file except in compliance with the License.
      5  # You may obtain a copy of the License at
      6  #
      7  #      http://www.apache.org/licenses/LICENSE-2.0
      8  #
      9  # Unless required by applicable law or agreed to in writing, software
     10  # distributed under the License is distributed on an "AS IS" BASIS,
     11  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  # See the License for the specific language governing permissions and
     13  # limitations under the License.
     14
     15  """Utilities for reading OAuth 2.0 client secret files.
     16
     17  A client_secrets.json file contains all the information needed to interact with
     18  an OAuth 2.0 protected service.
     19  """
     20
     21  __author__ = 'jcgregorio@google.com (Joe Gregorio)'
     22
     23
     24  from anyjson import simplejson
     25
     26  # Properties that make a client_secrets.json file valid.
     27  TYPE_WEB = 'web'
     28  TYPE_INSTALLED = 'installed'
     29
     30  VALID_CLIENT = {
     31      TYPE_WEB: {
     32          'required': [
     33              'client_id',
     34              'client_secret',
     35              'redirect_uris',
     36              'auth_uri',
     37              'token_uri',
     38          ],
     39          'string': [
     40              'client_id',
     41              'client_secret',
     42          ],
     43      },
     44      TYPE_INSTALLED: {
     45          'required': [
     46              'client_id',
     47              'client_secret',
     48              'redirect_uris',
     49              'auth_uri',
     50              'token_uri',
     51          ],
     52          'string': [
     53              'client_id',
     54              'client_secret',
     55          ],
     56      },
     57  }
     58
     59
     60 -class Error(Exception):
     61    """Base error for this module."""
     62    pass
     63
     64
     65 -class InvalidClientSecretsError(Error):
     66    """Format of ClientSecrets file is invalid."""
     67    pass
     68
     69
     70 -def _validate_clientsecrets(obj):
     71    if obj is None or len(obj) != 1:
     72      raise InvalidClientSecretsError('Invalid file format.')
     73    client_type = obj.keys()[0]
     74    if client_type not in VALID_CLIENT.keys():
     75      raise InvalidClientSecretsError('Unknown client type: %s.' % client_type)
     76    client_info = obj[client_type]
     77    for prop_name in VALID_CLIENT[client_type]['required']:
     78      if prop_name not in client_info:
     79        raise InvalidClientSecretsError(
     80          'Missing property "%s" in a client type of "%s".' % (prop_name,
     81                                                             client_type))
     82    for prop_name in VALID_CLIENT[client_type]['string']:
     83      if client_info[prop_name].startswith('[['):
     84        raise InvalidClientSecretsError(
     85          'Property "%s" is not configured.' % prop_name)
     86    return client_type, client_info
     87
     88
     89 -def load(fp):
     90    obj = simplejson.load(fp)
     91    return _validate_clientsecrets(obj)
     92
     93
     94 -def loads(s):
     95    obj = simplejson.loads(s)
     96    return _validate_clientsecrets(obj)
     97
     98
     99 -def _loadfile(filename):
    100    try:
    101      fp = file(filename, 'r')
    102      try:
    103        obj = simplejson.load(fp)
    104      finally:
    105        fp.close()
    106    except IOError:
    107      raise InvalidClientSecretsError('File not found: "%s"' % filename)
    108    return _validate_clientsecrets(obj)
    109
    110
    111 -def loadfile(filename, cache=None):
    112    """Loading of client_secrets JSON file, optionally backed by a cache.
    113
    114    Typical cache storage would be App Engine memcache service,
    115    but you can pass in any other cache client that implements
    116    these methods:
    117      - get(key, namespace=ns)
    118      - set(key, value, namespace=ns)
    119
    120    Usage:
    121      # without caching
    122      client_type, client_info = loadfile('secrets.json')
    123      # using App Engine memcache service
    124      from google.appengine.api import memcache
    125      client_type, client_info = loadfile('secrets.json', cache=memcache)
    126
    127    Args:
    128      filename: string, Path to a client_secrets.json file on a filesystem.
    129      cache: An optional cache service client that implements get() and set()
    130        methods. If not specified, the file is always being loaded from
    131        a filesystem.
    132
    133    Raises:
    134      InvalidClientSecretsError: In case of a validation error or some
    135        I/O failure. Can happen only on cache miss.
    136
    137    Returns:
    138      (client_type, client_info) tuple, as _loadfile() normally would.
    139      JSON contents is validated only during first load. Cache hits are not
    140      validated.
    141    """
    142    _SECRET_NAMESPACE = 'oauth2client:secrets#ns'
    143
    144    if not cache:
    145      return _loadfile(filename)
    146
    147    obj = cache.get(filename, namespace=_SECRET_NAMESPACE)
    148    if obj is None:
    149      client_type, client_info = _loadfile(filename)
    150      obj = {client_type: client_info}
    151      cache.set(filename, obj, namespace=_SECRET_NAMESPACE)
    152
    153    return obj.iteritems().next()
    154