_auth.py 5.6 KB

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