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 15"""OAuth 2.0 Async Credentials. 16 17This module provides credentials based on OAuth 2.0 access and refresh tokens. 18These credentials usually access resources on behalf of a user (resource 19owner). 20 21Specifically, this is intended to use access tokens acquired using the 22`Authorization Code grant`_ and can refresh those tokens using a 23optional `refresh token`_. 24 25Obtaining the initial access and refresh token is outside of the scope of this 26module. Consult `rfc6749 section 4.1`_ for complete details on the 27Authorization Code grant flow. 28 29.. _Authorization Code grant: https://tools.ietf.org/html/rfc6749#section-1.3.1 30.. _refresh token: https://tools.ietf.org/html/rfc6749#section-6 31.. _rfc6749 section 4.1: https://tools.ietf.org/html/rfc6749#section-4.1 32""" 33 34from google.auth import _credentials_async as credentials 35from google.auth import _helpers 36from google.auth import exceptions 37from google.oauth2 import _reauth_async as reauth 38from google.oauth2 import credentials as oauth2_credentials 39 40 41class Credentials(oauth2_credentials.Credentials): 42 """Credentials using OAuth 2.0 access and refresh tokens. 43 44 The credentials are considered immutable. If you want to modify the 45 quota project, use :meth:`with_quota_project` or :: 46 47 credentials = credentials.with_quota_project('myproject-123) 48 """ 49 50 @_helpers.copy_docstring(credentials.Credentials) 51 async def refresh(self, request): 52 if ( 53 self._refresh_token is None 54 or self._token_uri is None 55 or self._client_id is None 56 or self._client_secret is None 57 ): 58 raise exceptions.RefreshError( 59 "The credentials do not contain the necessary fields need to " 60 "refresh the access token. You must specify refresh_token, " 61 "token_uri, client_id, and client_secret." 62 ) 63 64 ( 65 access_token, 66 refresh_token, 67 expiry, 68 grant_response, 69 rapt_token, 70 ) = await reauth.refresh_grant( 71 request, 72 self._token_uri, 73 self._refresh_token, 74 self._client_id, 75 self._client_secret, 76 scopes=self._scopes, 77 rapt_token=self._rapt_token, 78 enable_reauth_refresh=self._enable_reauth_refresh, 79 ) 80 81 self.token = access_token 82 self.expiry = expiry 83 self._refresh_token = refresh_token 84 self._id_token = grant_response.get("id_token") 85 self._rapt_token = rapt_token 86 87 if self._scopes and "scope" in grant_response: 88 requested_scopes = frozenset(self._scopes) 89 granted_scopes = frozenset(grant_response["scope"].split()) 90 scopes_requested_but_not_granted = requested_scopes - granted_scopes 91 if scopes_requested_but_not_granted: 92 raise exceptions.RefreshError( 93 "Not all requested scopes were granted by the " 94 "authorization server, missing scopes {}.".format( 95 ", ".join(scopes_requested_but_not_granted) 96 ) 97 ) 98 99 100class UserAccessTokenCredentials(oauth2_credentials.UserAccessTokenCredentials): 101 """Access token credentials for user account. 102 103 Obtain the access token for a given user account or the current active 104 user account with the ``gcloud auth print-access-token`` command. 105 106 Args: 107 account (Optional[str]): Account to get the access token for. If not 108 specified, the current active account will be used. 109 quota_project_id (Optional[str]): The project ID used for quota 110 and billing. 111 112 """ 113