blob: da48be7635a4e08b38fb6d1b366379f7abdd0c0b [file] [log] [blame]
Joe Gregoriof08a4982011-10-07 13:11:16 -04001# 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
17A client_secrets.json file contains all the information needed to interact with
18an OAuth 2.0 protected service.
19"""
20
21__author__ = 'jcgregorio@google.com (Joe Gregorio)'
22
23
24try: # pragma: no cover
25 import simplejson
26except ImportError: # pragma: no cover
27 try:
28 # Try to import from django, should work on App Engine
29 from django.utils import simplejson
30 except ImportError:
31 # Should work for Python2.6 and higher.
32 import json as simplejson
33
34# Properties that make a client_secrets.json file valid.
35TYPE_WEB = 'web'
36TYPE_INSTALLED = 'installed'
37
38VALID_CLIENT = {
39 TYPE_WEB: {
40 'required': [
41 'client_id',
42 'client_secret',
43 'redirect_uris',
44 'auth_uri',
45 'token_uri'],
46 'string': [
47 'client_id',
48 'client_secret'
49 ]
50 },
51 TYPE_INSTALLED: {
52 'required': [
53 'client_id',
54 'client_secret',
55 'redirect_uris',
56 'auth_uri',
57 'token_uri'],
58 'string': [
59 'client_id',
60 'client_secret'
61 ]
62 }
63 }
64
65class Error(Exception):
66 """Base error for this module."""
67 pass
68
69
70class InvalidClientSecretsError(Error):
71 """Format of ClientSecrets file is invalid."""
72 pass
73
74
75def _validate_clientsecrets(obj):
76 if obj is None or len(obj) != 1:
77 raise InvalidClientSecretsError('Invalid file format.')
78 client_type = obj.keys()[0]
79 if client_type not in VALID_CLIENT.keys():
80 raise InvalidClientSecretsError('Unknown client type: %s.' % client_type)
81 client_info = obj[client_type]
82 for prop_name in VALID_CLIENT[client_type]['required']:
83 if prop_name not in client_info:
84 raise InvalidClientSecretsError(
85 'Missing property "%s" in a client type of "%s".' % (prop_name,
86 client_type))
87 for prop_name in VALID_CLIENT[client_type]['string']:
88 if client_info[prop_name].startswith('[['):
89 raise InvalidClientSecretsError(
90 'Property "%s" is not configured.' % prop_name)
91 return client_type, client_info
92
93
94def load(fp):
95 obj = simplejson.load(fp)
96 return _validate_clientsecrets(obj)
97
98
99def loads(s):
100 obj = simplejson.loads(s)
101 return _validate_clientsecrets(obj)
102
103
104def loadfile(filename):
105 try:
106 fp = file(filename, 'r')
107 try:
108 obj = simplejson.load(fp)
109 finally:
110 fp.close()
111 except IOError:
112 raise InvalidClientSecretsError('File not found: "%s"' % filename)
113 return _validate_clientsecrets(obj)