Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
id_token.py341 linesDownload Raw Back to oauth2
1# Copyright 2016 Google LLC2#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"""Google ID Token helpers.16 17Provides support for verifying `OpenID Connect ID Tokens`_, especially ones18generated by Google infrastructure.19 20To parse and verify an ID Token issued by Google's OAuth 2.0 authorization21server use :func:`verify_oauth2_token`. To verify an ID Token issued by22Firebase, use :func:`verify_firebase_token`.23 24A general purpose ID Token verifier is available as :func:`verify_token`.25 26Example::27 28    from google.oauth2 import id_token29    from google.auth.transport import requests30 31    request = requests.Request()32 33    id_info = id_token.verify_oauth2_token(34        token, request, 'my-client-id.example.com')35 36    userid = id_info['sub']37 38By default, this will re-fetch certificates for each verification. Because39Google's public keys are only changed infrequently (on the order of once per40day), you may wish to take advantage of caching to reduce latency and the41potential for network errors. This can be accomplished using an external42library like `CacheControl`_ to create a cache-aware43:class:`google.auth.transport.Request`::44 45    import cachecontrol46    import google.auth.transport.requests47    import requests48 49    session = requests.session()50    cached_session = cachecontrol.CacheControl(session)51    request = google.auth.transport.requests.Request(session=cached_session)52 53.. _OpenID Connect ID Tokens:54    http://openid.net/specs/openid-connect-core-1_0.html#IDToken55.. _CacheControl: https://cachecontrol.readthedocs.io56"""57 58import http.client as http_client59import json60import os61 62from google.auth import environment_vars63from google.auth import exceptions64from google.auth import jwt65 66 67# The URL that provides public certificates for verifying ID tokens issued68# by Google's OAuth 2.0 authorization server.69_GOOGLE_OAUTH2_CERTS_URL = "https://www.googleapis.com/oauth2/v1/certs"70 71# The URL that provides public certificates for verifying ID tokens issued72# by Firebase and the Google APIs infrastructure73_GOOGLE_APIS_CERTS_URL = (74    "https://www.googleapis.com/robot/v1/metadata/x509"75    "/securetoken@system.gserviceaccount.com"76)77 78_GOOGLE_ISSUERS = ["accounts.google.com", "https://accounts.google.com"]79 80 81def _fetch_certs(request, certs_url):82    """Fetches certificates.83 84    Google-style cerificate endpoints return JSON in the format of85    ``{'key id': 'x509 certificate'}``.86 87    Args:88        request (google.auth.transport.Request): The object used to make89            HTTP requests.90        certs_url (str): The certificate endpoint URL.91 92    Returns:93        Mapping[str, str]: A mapping of public key ID to x.509 certificate94            data.95    """96    response = request(certs_url, method="GET")97 98    if response.status != http_client.OK:99        raise exceptions.TransportError(100            "Could not fetch certificates at {}".format(certs_url)101        )102 103    return json.loads(response.data.decode("utf-8"))104 105 106def verify_token(107    id_token,108    request,109    audience=None,110    certs_url=_GOOGLE_OAUTH2_CERTS_URL,111    clock_skew_in_seconds=0,112):113    """Verifies an ID token and returns the decoded token.114 115    Args:116        id_token (Union[str, bytes]): The encoded token.117        request (google.auth.transport.Request): The object used to make118            HTTP requests.119        audience (str or list): The audience or audiences that this token is120            intended for. If None then the audience is not verified.121        certs_url (str): The URL that specifies the certificates to use to122            verify the token. This URL should return JSON in the format of123            ``{'key id': 'x509 certificate'}``.124        clock_skew_in_seconds (int): The clock skew used for `iat` and `exp`125            validation.126 127    Returns:128        Mapping[str, Any]: The decoded token.129    """130    certs = _fetch_certs(request, certs_url)131 132    return jwt.decode(133        id_token,134        certs=certs,135        audience=audience,136        clock_skew_in_seconds=clock_skew_in_seconds,137    )138 139 140def verify_oauth2_token(id_token, request, audience=None, clock_skew_in_seconds=0):141    """Verifies an ID Token issued by Google's OAuth 2.0 authorization server.142 143    Args:144        id_token (Union[str, bytes]): The encoded token.145        request (google.auth.transport.Request): The object used to make146            HTTP requests.147        audience (str): The audience that this token is intended for. This is148            typically your application's OAuth 2.0 client ID. If None then the149            audience is not verified.150        clock_skew_in_seconds (int): The clock skew used for `iat` and `exp`151            validation.152 153    Returns:154        Mapping[str, Any]: The decoded token.155 156    Raises:157        exceptions.GoogleAuthError: If the issuer is invalid.158        ValueError: If token verification fails159    """160    idinfo = verify_token(161        id_token,162        request,163        audience=audience,164        certs_url=_GOOGLE_OAUTH2_CERTS_URL,165        clock_skew_in_seconds=clock_skew_in_seconds,166    )167 168    if idinfo["iss"] not in _GOOGLE_ISSUERS:169        raise exceptions.GoogleAuthError(170            "Wrong issuer. 'iss' should be one of the following: {}".format(171                _GOOGLE_ISSUERS172            )173        )174 175    return idinfo176 177 178def verify_firebase_token(id_token, request, audience=None, clock_skew_in_seconds=0):179    """Verifies an ID Token issued by Firebase Authentication.180 181    Args:182        id_token (Union[str, bytes]): The encoded token.183        request (google.auth.transport.Request): The object used to make184            HTTP requests.185        audience (str): The audience that this token is intended for. This is186            typically your Firebase application ID. If None then the audience187            is not verified.188        clock_skew_in_seconds (int): The clock skew used for `iat` and `exp`189            validation.190 191    Returns:192        Mapping[str, Any]: The decoded token.193    """194    return verify_token(195        id_token,196        request,197        audience=audience,198        certs_url=_GOOGLE_APIS_CERTS_URL,199        clock_skew_in_seconds=clock_skew_in_seconds,200    )201 202 203def fetch_id_token_credentials(audience, request=None):204    """Create the ID Token credentials from the current environment.205 206    This function acquires ID token from the environment in the following order.207    See https://google.aip.dev/auth/4110.208 209    1. If the environment variable ``GOOGLE_APPLICATION_CREDENTIALS`` is set210       to the path of a valid service account JSON file, then ID token is211       acquired using this service account credentials.212    2. If the application is running in Compute Engine, App Engine or Cloud Run,213       then the ID token are obtained from the metadata server.214    3. If metadata server doesn't exist and no valid service account credentials215       are found, :class:`~google.auth.exceptions.DefaultCredentialsError` will216       be raised.217 218    Example::219 220        import google.oauth2.id_token221        import google.auth.transport.requests222 223        request = google.auth.transport.requests.Request()224        target_audience = "https://pubsub.googleapis.com"225 226        # Create ID token credentials.227        credentials = google.oauth2.id_token.fetch_id_token_credentials(target_audience, request=request)228 229        # Refresh the credential to obtain an ID token.230        credentials.refresh(request)231 232        id_token = credentials.token233        id_token_expiry = credentials.expiry234 235    Args:236        audience (str): The audience that this ID token is intended for.237        request (Optional[google.auth.transport.Request]): A callable used to make238            HTTP requests. A request object will be created if not provided.239 240    Returns:241        google.auth.credentials.Credentials: The ID token credentials.242 243    Raises:244        ~google.auth.exceptions.DefaultCredentialsError:245            If metadata server doesn't exist and no valid service account246            credentials are found.247    """248    # 1. Try to get credentials from the GOOGLE_APPLICATION_CREDENTIALS environment249    # variable.250    credentials_filename = os.environ.get(environment_vars.CREDENTIALS)251    if credentials_filename:252        if not (253            os.path.exists(credentials_filename)254            and os.path.isfile(credentials_filename)255        ):256            raise exceptions.DefaultCredentialsError(257                "GOOGLE_APPLICATION_CREDENTIALS path is either not found or invalid."258            )259 260        try:261            with open(credentials_filename, "r") as f:262                from google.oauth2 import service_account263 264                info = json.load(f)265                if info.get("type") == "service_account":266                    return service_account.IDTokenCredentials.from_service_account_info(267                        info, target_audience=audience268                    )269        except ValueError as caught_exc:270            new_exc = exceptions.DefaultCredentialsError(271                "GOOGLE_APPLICATION_CREDENTIALS is not valid service account credentials.",272                caught_exc,273            )274            raise new_exc from caught_exc275 276    # 2. Try to fetch ID token from metada server if it exists. The code277    # works for GAE and Cloud Run metadata server as well.278    try:279        from google.auth import compute_engine280        from google.auth.compute_engine import _metadata281 282        # Create a request object if not provided.283        if not request:284            import google.auth.transport.requests285 286            request = google.auth.transport.requests.Request()287 288        if _metadata.ping(request):289            return compute_engine.IDTokenCredentials(290                request, audience, use_metadata_identity_endpoint=True291            )292    except (ImportError, exceptions.TransportError):293        pass294 295    raise exceptions.DefaultCredentialsError(296        "Neither metadata server or valid service account credentials are found."297    )298 299 300def fetch_id_token(request, audience):301    """Fetch the ID Token from the current environment.302 303    This function acquires ID token from the environment in the following order.304    See https://google.aip.dev/auth/4110.305 306    1. If the environment variable ``GOOGLE_APPLICATION_CREDENTIALS`` is set307       to the path of a valid service account JSON file, then ID token is308       acquired using this service account credentials.309    2. If the application is running in Compute Engine, App Engine or Cloud Run,310       then the ID token are obtained from the metadata server.311    3. If metadata server doesn't exist and no valid service account credentials312       are found, :class:`~google.auth.exceptions.DefaultCredentialsError` will313       be raised.314 315    Example::316 317        import google.oauth2.id_token318        import google.auth.transport.requests319 320        request = google.auth.transport.requests.Request()321        target_audience = "https://pubsub.googleapis.com"322 323        id_token = google.oauth2.id_token.fetch_id_token(request, target_audience)324 325    Args:326        request (google.auth.transport.Request): A callable used to make327            HTTP requests.328        audience (str): The audience that this ID token is intended for.329 330    Returns:331        str: The ID token.332 333    Raises:334        ~google.auth.exceptions.DefaultCredentialsError:335            If metadata server doesn't exist and no valid service account336            credentials are found.337    """338    id_token_credentials = fetch_id_token_credentials(audience, request=request)339    id_token_credentials.refresh(request)340    return id_token_credentials.token341 
codekingpro/portable-devtools · Team Ai