_credentials_async.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. # Copyright 2020 Google LLC
  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. """Interfaces for credentials."""
  15. import abc
  16. import inspect
  17. from google.auth import credentials
  18. class Credentials(credentials.Credentials, metaclass=abc.ABCMeta):
  19. """Async inherited credentials class from google.auth.credentials.
  20. The added functionality is the before_request call which requires
  21. async/await syntax.
  22. All credentials have a :attr:`token` that is used for authentication and
  23. may also optionally set an :attr:`expiry` to indicate when the token will
  24. no longer be valid.
  25. Most credentials will be :attr:`invalid` until :meth:`refresh` is called.
  26. Credentials can do this automatically before the first HTTP request in
  27. :meth:`before_request`.
  28. Although the token and expiration will change as the credentials are
  29. :meth:`refreshed <refresh>` and used, credentials should be considered
  30. immutable. Various credentials will accept configuration such as private
  31. keys, scopes, and other options. These options are not changeable after
  32. construction. Some classes will provide mechanisms to copy the credentials
  33. with modifications such as :meth:`ScopedCredentials.with_scopes`.
  34. """
  35. async def before_request(self, request, method, url, headers):
  36. """Performs credential-specific before request logic.
  37. Refreshes the credentials if necessary, then calls :meth:`apply` to
  38. apply the token to the authentication header.
  39. Args:
  40. request (google.auth.transport.Request): The object used to make
  41. HTTP requests.
  42. method (str): The request's HTTP method or the RPC method being
  43. invoked.
  44. url (str): The request's URI or the RPC service's URI.
  45. headers (Mapping): The request's headers.
  46. """
  47. # pylint: disable=unused-argument
  48. # (Subclasses may use these arguments to ascertain information about
  49. # the http request.)
  50. if not self.valid:
  51. if inspect.iscoroutinefunction(self.refresh):
  52. await self.refresh(request)
  53. else:
  54. self.refresh(request)
  55. self.apply(headers)
  56. class CredentialsWithQuotaProject(credentials.CredentialsWithQuotaProject):
  57. """Abstract base for credentials supporting ``with_quota_project`` factory"""
  58. class AnonymousCredentials(credentials.AnonymousCredentials, Credentials):
  59. """Credentials that do not provide any authentication information.
  60. These are useful in the case of services that support anonymous access or
  61. local service emulators that do not use credentials. This class inherits
  62. from the sync anonymous credentials file, but is kept if async credentials
  63. is initialized and we would like anonymous credentials.
  64. """
  65. class ReadOnlyScoped(credentials.ReadOnlyScoped, metaclass=abc.ABCMeta):
  66. """Interface for credentials whose scopes can be queried.
  67. OAuth 2.0-based credentials allow limiting access using scopes as described
  68. in `RFC6749 Section 3.3`_.
  69. If a credential class implements this interface then the credentials either
  70. use scopes in their implementation.
  71. Some credentials require scopes in order to obtain a token. You can check
  72. if scoping is necessary with :attr:`requires_scopes`::
  73. if credentials.requires_scopes:
  74. # Scoping is required.
  75. credentials = _credentials_async.with_scopes(scopes=['one', 'two'])
  76. Credentials that require scopes must either be constructed with scopes::
  77. credentials = SomeScopedCredentials(scopes=['one', 'two'])
  78. Or must copy an existing instance using :meth:`with_scopes`::
  79. scoped_credentials = _credentials_async.with_scopes(scopes=['one', 'two'])
  80. Some credentials have scopes but do not allow or require scopes to be set,
  81. these credentials can be used as-is.
  82. .. _RFC6749 Section 3.3: https://tools.ietf.org/html/rfc6749#section-3.3
  83. """
  84. class Scoped(credentials.Scoped):
  85. """Interface for credentials whose scopes can be replaced while copying.
  86. OAuth 2.0-based credentials allow limiting access using scopes as described
  87. in `RFC6749 Section 3.3`_.
  88. If a credential class implements this interface then the credentials either
  89. use scopes in their implementation.
  90. Some credentials require scopes in order to obtain a token. You can check
  91. if scoping is necessary with :attr:`requires_scopes`::
  92. if credentials.requires_scopes:
  93. # Scoping is required.
  94. credentials = _credentials_async.create_scoped(['one', 'two'])
  95. Credentials that require scopes must either be constructed with scopes::
  96. credentials = SomeScopedCredentials(scopes=['one', 'two'])
  97. Or must copy an existing instance using :meth:`with_scopes`::
  98. scoped_credentials = credentials.with_scopes(scopes=['one', 'two'])
  99. Some credentials have scopes but do not allow or require scopes to be set,
  100. these credentials can be used as-is.
  101. .. _RFC6749 Section 3.3: https://tools.ietf.org/html/rfc6749#section-3.3
  102. """
  103. def with_scopes_if_required(credentials, scopes):
  104. """Creates a copy of the credentials with scopes if scoping is required.
  105. This helper function is useful when you do not know (or care to know) the
  106. specific type of credentials you are using (such as when you use
  107. :func:`google.auth.default`). This function will call
  108. :meth:`Scoped.with_scopes` if the credentials are scoped credentials and if
  109. the credentials require scoping. Otherwise, it will return the credentials
  110. as-is.
  111. Args:
  112. credentials (google.auth.credentials.Credentials): The credentials to
  113. scope if necessary.
  114. scopes (Sequence[str]): The list of scopes to use.
  115. Returns:
  116. google.auth._credentials_async.Credentials: Either a new set of scoped
  117. credentials, or the passed in credentials instance if no scoping
  118. was required.
  119. """
  120. if isinstance(credentials, Scoped) and credentials.requires_scopes:
  121. return credentials.with_scopes(scopes)
  122. else:
  123. return credentials
  124. class Signing(credentials.Signing, metaclass=abc.ABCMeta):
  125. """Interface for credentials that can cryptographically sign messages."""