• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 Google Inc. All Rights Reserved.
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"""Helpers for authentication using oauth2client or google-auth."""
16
17import httplib2
18
19try:
20    import google.auth
21    import google.auth.credentials
22    HAS_GOOGLE_AUTH = True
23except ImportError:  # pragma: NO COVER
24    HAS_GOOGLE_AUTH = False
25
26try:
27    import google_auth_httplib2
28except ImportError:  # pragma: NO COVER
29    google_auth_httplib2 = None
30
31try:
32    import oauth2client
33    import oauth2client.client
34    HAS_OAUTH2CLIENT = True
35except ImportError:  # pragma: NO COVER
36    HAS_OAUTH2CLIENT = False
37
38
39def default_credentials():
40    """Returns Application Default Credentials."""
41    if HAS_GOOGLE_AUTH:
42        credentials, _ = google.auth.default()
43        return credentials
44    elif HAS_OAUTH2CLIENT:
45        return oauth2client.client.GoogleCredentials.get_application_default()
46    else:
47        raise EnvironmentError(
48            'No authentication library is available. Please install either '
49            'google-auth or oauth2client.')
50
51
52def with_scopes(credentials, scopes):
53    """Scopes the credentials if necessary.
54
55    Args:
56        credentials (Union[
57            google.auth.credentials.Credentials,
58            oauth2client.client.Credentials]): The credentials to scope.
59        scopes (Sequence[str]): The list of scopes.
60
61    Returns:
62        Union[google.auth.credentials.Credentials,
63            oauth2client.client.Credentials]: The scoped credentials.
64    """
65    if HAS_GOOGLE_AUTH and isinstance(
66            credentials, google.auth.credentials.Credentials):
67        return google.auth.credentials.with_scopes_if_required(
68            credentials, scopes)
69    else:
70        try:
71            if credentials.create_scoped_required():
72                return credentials.create_scoped(scopes)
73            else:
74                return credentials
75        except AttributeError:
76            return credentials
77
78
79def authorized_http(credentials):
80    """Returns an http client that is authorized with the given credentials.
81
82    Args:
83        credentials (Union[
84            google.auth.credentials.Credentials,
85            oauth2client.client.Credentials]): The credentials to use.
86
87    Returns:
88        Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
89            authorized http client.
90    """
91    from googleapiclient.http import build_http
92
93    if HAS_GOOGLE_AUTH and isinstance(
94            credentials, google.auth.credentials.Credentials):
95        if google_auth_httplib2 is None:
96            raise ValueError(
97                'Credentials from google.auth specified, but '
98                'google-api-python-client is unable to use these credentials '
99                'unless google-auth-httplib2 is installed. Please install '
100                'google-auth-httplib2.')
101        return google_auth_httplib2.AuthorizedHttp(credentials,
102                                                   http=build_http())
103    else:
104        return credentials.authorize(build_http())
105
106
107def refresh_credentials(credentials):
108    # Refresh must use a new http instance, as the one associated with the
109    # credentials could be a AuthorizedHttp or an oauth2client-decorated
110    # Http instance which would cause a weird recursive loop of refreshing
111    # and likely tear a hole in spacetime.
112    refresh_http = httplib2.Http()
113    if HAS_GOOGLE_AUTH and isinstance(
114            credentials, google.auth.credentials.Credentials):
115        request = google_auth_httplib2.Request(refresh_http)
116        return credentials.refresh(request)
117    else:
118        return credentials.refresh(refresh_http)
119
120
121def apply_credentials(credentials, headers):
122    # oauth2client and google-auth have the same interface for this.
123    if not is_valid(credentials):
124        refresh_credentials(credentials)
125    return credentials.apply(headers)
126
127
128def is_valid(credentials):
129    if HAS_GOOGLE_AUTH and isinstance(
130            credentials, google.auth.credentials.Credentials):
131        return credentials.valid
132    else:
133        return (
134            credentials.access_token is not None and
135            not credentials.access_token_expired)
136
137
138def get_credentials_from_http(http):
139    if http is None:
140        return None
141    elif hasattr(http.request, 'credentials'):
142        return http.request.credentials
143    elif (hasattr(http, 'credentials')
144          and not isinstance(http.credentials, httplib2.Credentials)):
145        return http.credentials
146    else:
147        return None
148