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