| # Copyright 2020 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| |
| """Interfaces for credentials.""" |
| |
| import abc |
| import inspect |
| |
| import six |
| |
| from google.auth import credentials |
| |
| |
| @six.add_metaclass(abc.ABCMeta) |
| class Credentials(credentials.Credentials): |
| """Async inherited credentials class from google.auth.credentials. |
| The added functionality is the before_request call which requires |
| async/await syntax. |
| All credentials have a :attr:`token` that is used for authentication and |
| may also optionally set an :attr:`expiry` to indicate when the token will |
| no longer be valid. |
| |
| Most credentials will be :attr:`invalid` until :meth:`refresh` is called. |
| Credentials can do this automatically before the first HTTP request in |
| :meth:`before_request`. |
| |
| Although the token and expiration will change as the credentials are |
| :meth:`refreshed <refresh>` and used, credentials should be considered |
| immutable. Various credentials will accept configuration such as private |
| keys, scopes, and other options. These options are not changeable after |
| construction. Some classes will provide mechanisms to copy the credentials |
| with modifications such as :meth:`ScopedCredentials.with_scopes`. |
| """ |
| |
| async def before_request(self, request, method, url, headers): |
| """Performs credential-specific before request logic. |
| |
| Refreshes the credentials if necessary, then calls :meth:`apply` to |
| apply the token to the authentication header. |
| |
| Args: |
| request (google.auth.transport.Request): The object used to make |
| HTTP requests. |
| method (str): The request's HTTP method or the RPC method being |
| invoked. |
| url (str): The request's URI or the RPC service's URI. |
| headers (Mapping): The request's headers. |
| """ |
| # pylint: disable=unused-argument |
| # (Subclasses may use these arguments to ascertain information about |
| # the http request.) |
| |
| if not self.valid: |
| if inspect.iscoroutinefunction(self.refresh): |
| await self.refresh(request) |
| else: |
| self.refresh(request) |
| self.apply(headers) |
| |
| |
| class CredentialsWithQuotaProject(credentials.CredentialsWithQuotaProject): |
| """Abstract base for credentials supporting ``with_quota_project`` factory""" |
| |
| |
| class AnonymousCredentials(credentials.AnonymousCredentials, Credentials): |
| """Credentials that do not provide any authentication information. |
| |
| These are useful in the case of services that support anonymous access or |
| local service emulators that do not use credentials. This class inherits |
| from the sync anonymous credentials file, but is kept if async credentials |
| is initialized and we would like anonymous credentials. |
| """ |
| |
| |
| @six.add_metaclass(abc.ABCMeta) |
| class ReadOnlyScoped(credentials.ReadOnlyScoped): |
| """Interface for credentials whose scopes can be queried. |
| |
| OAuth 2.0-based credentials allow limiting access using scopes as described |
| in `RFC6749 Section 3.3`_. |
| If a credential class implements this interface then the credentials either |
| use scopes in their implementation. |
| |
| Some credentials require scopes in order to obtain a token. You can check |
| if scoping is necessary with :attr:`requires_scopes`:: |
| |
| if credentials.requires_scopes: |
| # Scoping is required. |
| credentials = _credentials_async.with_scopes(scopes=['one', 'two']) |
| |
| Credentials that require scopes must either be constructed with scopes:: |
| |
| credentials = SomeScopedCredentials(scopes=['one', 'two']) |
| |
| Or must copy an existing instance using :meth:`with_scopes`:: |
| |
| scoped_credentials = _credentials_async.with_scopes(scopes=['one', 'two']) |
| |
| Some credentials have scopes but do not allow or require scopes to be set, |
| these credentials can be used as-is. |
| |
| .. _RFC6749 Section 3.3: https://tools.ietf.org/html/rfc6749#section-3.3 |
| """ |
| |
| |
| class Scoped(credentials.Scoped): |
| """Interface for credentials whose scopes can be replaced while copying. |
| |
| OAuth 2.0-based credentials allow limiting access using scopes as described |
| in `RFC6749 Section 3.3`_. |
| If a credential class implements this interface then the credentials either |
| use scopes in their implementation. |
| |
| Some credentials require scopes in order to obtain a token. You can check |
| if scoping is necessary with :attr:`requires_scopes`:: |
| |
| if credentials.requires_scopes: |
| # Scoping is required. |
| credentials = _credentials_async.create_scoped(['one', 'two']) |
| |
| Credentials that require scopes must either be constructed with scopes:: |
| |
| credentials = SomeScopedCredentials(scopes=['one', 'two']) |
| |
| Or must copy an existing instance using :meth:`with_scopes`:: |
| |
| scoped_credentials = credentials.with_scopes(scopes=['one', 'two']) |
| |
| Some credentials have scopes but do not allow or require scopes to be set, |
| these credentials can be used as-is. |
| |
| .. _RFC6749 Section 3.3: https://tools.ietf.org/html/rfc6749#section-3.3 |
| """ |
| |
| |
| def with_scopes_if_required(credentials, scopes): |
| """Creates a copy of the credentials with scopes if scoping is required. |
| |
| This helper function is useful when you do not know (or care to know) the |
| specific type of credentials you are using (such as when you use |
| :func:`google.auth.default`). This function will call |
| :meth:`Scoped.with_scopes` if the credentials are scoped credentials and if |
| the credentials require scoping. Otherwise, it will return the credentials |
| as-is. |
| |
| Args: |
| credentials (google.auth.credentials.Credentials): The credentials to |
| scope if necessary. |
| scopes (Sequence[str]): The list of scopes to use. |
| |
| Returns: |
| google.auth._credentials_async.Credentials: Either a new set of scoped |
| credentials, or the passed in credentials instance if no scoping |
| was required. |
| """ |
| if isinstance(credentials, Scoped) and credentials.requires_scopes: |
| return credentials.with_scopes(scopes) |
| else: |
| return credentials |
| |
| |
| @six.add_metaclass(abc.ABCMeta) |
| class Signing(credentials.Signing): |
| """Interface for credentials that can cryptographically sign messages.""" |