codekingpro/portable-devtools
114k
1# Copyright 2017 Google Inc.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 at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# 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 and13# limitations under the License.14 15"""Integration helpers.16 17This module provides helpers for integrating with `requests-oauthlib`_.18Typically, you'll want to use the higher-level helpers in19:mod:`google_auth_oauthlib.flow`.20 21.. _requests-oauthlib: http://requests-oauthlib.readthedocs.io/en/latest/22"""23 24import datetime25import json26 27from google.auth import external_account_authorized_user28import google.oauth2.credentials29import requests_oauthlib30 31_REQUIRED_CONFIG_KEYS = frozenset(("auth_uri", "token_uri", "client_id"))32 33 34def session_from_client_config(client_config, scopes, **kwargs):35 """Creates a :class:`requests_oauthlib.OAuth2Session` from client36 configuration loaded from a Google-format client secrets file.37 38 Args:39 client_config (Mapping[str, Any]): The client40 configuration in the Google `client secrets`_ format.41 scopes (Sequence[str]): The list of scopes to request during the42 flow.43 kwargs: Any additional parameters passed to44 :class:`requests_oauthlib.OAuth2Session`45 46 Raises:47 ValueError: If the client configuration is not in the correct48 format.49 50 Returns:51 Tuple[requests_oauthlib.OAuth2Session, Mapping[str, Any]]: The new52 oauthlib session and the validated client configuration.53 54 .. _client secrets:55 https://github.com/googleapis/google-api-python-client/blob/main/docs/client-secrets.md56 """57 58 if "web" in client_config:59 config = client_config["web"]60 elif "installed" in client_config:61 config = client_config["installed"]62 else:63 raise ValueError("Client secrets must be for a web or installed app.")64 65 if not _REQUIRED_CONFIG_KEYS.issubset(config.keys()):66 raise ValueError("Client secrets is not in the correct format.")67 68 session = requests_oauthlib.OAuth2Session(69 client_id=config["client_id"], scope=scopes, **kwargs70 )71 72 return session, client_config73 74 75def session_from_client_secrets_file(client_secrets_file, scopes, **kwargs):76 """Creates a :class:`requests_oauthlib.OAuth2Session` instance from a77 Google-format client secrets file.78 79 Args:80 client_secrets_file (str): The path to the `client secrets`_ .json81 file.82 scopes (Sequence[str]): The list of scopes to request during the83 flow.84 kwargs: Any additional parameters passed to85 :class:`requests_oauthlib.OAuth2Session`86 87 Returns:88 Tuple[requests_oauthlib.OAuth2Session, Mapping[str, Any]]: The new89 oauthlib session and the validated client configuration.90 91 .. _client secrets:92 https://github.com/googleapis/google-api-python-client/blob/main/docs/client-secrets.md93 """94 with open(client_secrets_file, "r") as json_file:95 client_config = json.load(json_file)96 97 return session_from_client_config(client_config, scopes, **kwargs)98 99 100def credentials_from_session(session, client_config=None):101 """Creates :class:`google.oauth2.credentials.Credentials` from a102 :class:`requests_oauthlib.OAuth2Session`.103 104 :meth:`fetch_token` must be called on the session before before calling105 this. This uses the session's auth token and the provided client106 configuration to create :class:`google.oauth2.credentials.Credentials`.107 This allows you to use the credentials from the session with Google108 API client libraries.109 110 Args:111 session (requests_oauthlib.OAuth2Session): The OAuth 2.0 session.112 client_config (Mapping[str, Any]): The subset of the client113 configuration to use. For example, if you have a web client114 you would pass in `client_config['web']`.115 116 Returns:117 google.oauth2.credentials.Credentials: The constructed credentials.118 119 Raises:120 ValueError: If there is no access token in the session.121 """122 client_config = client_config if client_config is not None else {}123 124 if not session.token:125 raise ValueError(126 "There is no access token for this session, did you call " "fetch_token?"127 )128 129 if "3pi" in client_config:130 credentials = external_account_authorized_user.Credentials(131 token=session.token["access_token"],132 refresh_token=session.token.get("refresh_token"),133 token_url=client_config.get("token_uri"),134 client_id=client_config.get("client_id"),135 client_secret=client_config.get("client_secret"),136 token_info_url=client_config.get("token_info_url"),137 scopes=session.scope,138 )139 else:140 credentials = google.oauth2.credentials.Credentials(141 session.token["access_token"],142 refresh_token=session.token.get("refresh_token"),143 id_token=session.token.get("id_token"),144 token_uri=client_config.get("token_uri"),145 client_id=client_config.get("client_id"),146 client_secret=client_config.get("client_secret"),147 scopes=session.scope,148 granted_scopes=session.token.get("scope"),149 )150 credentials.expiry = datetime.datetime.utcfromtimestamp(session.token["expires_at"])151 return credentials152 