Ejemplo n.º 1
0
 def check_authorization(*args, **kwargs):
     if request.headers.get(ENDPOINTS_HEADER):
         dec = base64.b64decode(request.headers.get(ENDPOINTS_HEADER))
         token = request.headers.get(AUTHORIZATION_HEADER)
         token = token.split(' ')[1]
         r = google.auth.transport.requests.Request()
         id_token.verify_token(token, r)
     else:
         api.abort(401, ENDPOINTS_HEADER + ' header required')
     return f(*args, **kwargs)
Ejemplo n.º 2
0
 def intercept_service(self, continuation, handler_call_details):
     try:
         for k in handler_call_details.invocation_metadata:
             if (k.key.lower() == AUTHORIZATION_HEADER):
                 token = k.value
                 token = token.split(' ')[1]
                 r = google.auth.transport.requests.Request()
                 id_token.verify_token(token, r)
                 return continuation(handler_call_details)
         return self._terminator
     except:
         return self._terminator
Ejemplo n.º 3
0
 def check_authorization(*args, **kwargs):
     if request.headers.get(AUTHORIZATION_HEADER):
         token = request.headers.get(AUTHORIZATION_HEADER)
         # Do JWT validation for IAP here in a similar way to the check below for google_id_token
         # note, IAP uses EC so you need to validate the JWTs for that scheme
         # you may need to use a library which does ES256 validation using
         # JWK like https://github.com/mpdavis/python-jose
         # ...the following is for GoogleIDToken and uses RS256...i added this in just as a
         # middleware example
         token = token.split(' ')[1]
         r = google.auth.transport.requests.Request()
         id_token.verify_token(token, r)
     else:
         api.abort(401, AUTHORIZATION_HEADER + ' header required')
     return f(*args, **kwargs)
Ejemplo n.º 4
0
def _validate_id_token(token):
    idinfo = id_token.verify_token(token, request)
    if idinfo['iss'] not in [
            'accounts.google.com', 'https://accounts.google.com'
    ]:
        raise ApplicationIdentityError
    ## TODO(dek): implement additional checks from the Google OAuth examples server-side example page
    return idinfo
Ejemplo n.º 5
0
def google_info_from_token(token):
    idinfo = id_token.verify_token(token, settings.GOOGLE_CLIENT_ID)
    if idinfo['aud'] != settings.GOOGLE_CLIENT_ID:
        raise GoogleAuthError('aud dont match')
    if idinfo['iss'] not in [
            'accounts.google.com', 'https://accounts.google.com'
    ]:
        raise GoogleAuthError("Wrong issuer.")
    return idinfo
def gcp_instance_validation(node_fqdn, challenge_password, audience):
    payload = id_token.verify_token(challenge_password,
                                    request=Request(),
                                    audience=audience)

    if check_payload(payload):
        exit(0)
    else:
        exit(1)
Ejemplo n.º 7
0
def get_user_google(token):
    user = id_token.verify_token(token, google_requests.Request(),
                                 GOOGLE_CLIENT_ID)
    if user['iss'] not in [
            'accounts.google.com', 'https://accounts.google.com'
    ] or 'email' not in user:
        raise ValueError('Wrong issuer.')
    else:
        return user
Ejemplo n.º 8
0
def test_verify_token(_fetch_certs, decode):
    result = id_token.verify_token(mock.sentinel.token, mock.sentinel.request)

    assert result == decode.return_value
    _fetch_certs.assert_called_once_with(mock.sentinel.request,
                                         id_token._GOOGLE_OAUTH2_CERTS_URL)
    decode.assert_called_once_with(mock.sentinel.token,
                                   certs=_fetch_certs.return_value,
                                   audience=None)
Ejemplo n.º 9
0
def run():
    buf = []
    for line in fileinput.input():
        buf.append(line.rstrip('\n'))
    buf.append("===")
    audience = os.environ['AUDIENCE']
    token = ''.join(buf)
    request = google.auth.transport.requests.Request()
    payload = id_token.verify_token(token, request=request, audience=audience)
    print(payload)
Ejemplo n.º 10
0
def verifyToken(token,audience):
  JWK_URL = 'https://www.googleapis.com/service_accounts/v1/jwk/' + cred.service_account_email
  X509_URL ='https://www.googleapis.com/service_accounts/v1/metadata/x509/' + cred.service_account_email

  request = google.auth.transport.requests.Request()
  id_info = id_token.verify_token(
      token, request, audience, certs_url=X509_URL)

  if id_info['iss'] != cred.service_account_email:
      raise ValueError('Wrong issuer.')
  print(id_info['sub'])
Ejemplo n.º 11
0
def VerifyIDToken(token, audience=None):
    """
  Input: ID Token String, Target Audience Endpoint
  Output: True if token is still valid, False if invalid
  """
    certs_url = 'https://www.googleapis.com/oauth2/v1/certs'
    request = google.auth.transport.requests.Request()
    result = id_token.verify_token(token, request, certs_url=certs_url)
    if audience in result['aud']:
        return True
    return False
Ejemplo n.º 12
0
def test_verify_token_args(_fetch_certs, decode):
    result = id_token.verify_token(mock.sentinel.token,
                                   mock.sentinel.request,
                                   audience=mock.sentinel.audience,
                                   certs_url=mock.sentinel.certs_url)

    assert result == decode.return_value
    _fetch_certs.assert_called_once_with(mock.sentinel.request,
                                         mock.sentinel.certs_url)
    decode.assert_called_once_with(mock.sentinel.token,
                                   certs=_fetch_certs.return_value,
                                   audience=mock.sentinel.audience)
Ejemplo n.º 13
0
 def _check_token(self, bot_token: Text) -> None:
     # see https://developers.google.com/chat/how-tos/bots-develop#verifying_bot_authenticity # noqa: E501, W505
     # and https://google-auth.readthedocs.io/en/latest/user-guide.html#identity-tokens # noqa: E501, W505
     try:
         decoded_token = id_token.verify_token(
             bot_token,
             self.google_request,
             audience=self.project_id,
             certs_url=CERTS_URL,
         )
     except ValueError:
         raise SanicException(status_code=401)
     if decoded_token["iss"] != "*****@*****.**":
         raise SanicException(status_code=401)
Ejemplo n.º 14
0
    def post(self, request):
        token = {'id_token': request.data.get('id_token')}
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        try:
            idinfo = id_token.verify_token(token['id_token'],
                                           requests.Request())
            if idinfo['aud'] not in [
                    FIREBASE_ANDROID_APP_ID, FIREBASE_IOS_APP_ID
            ]:
                raise ValueError('Could not verify audience.')

            if idinfo['iss'] not in [
                    'accounts.google.com', 'https://accounts.google.com'
            ]:
                raise ValueError('Wrong issuer.')

            if User.objects.filter(
                    Q(email=idinfo['email'])
                    | Q(username=idinfo['email'])).exists():
                user = User.objects.get(email=idinfo['email'])
            else:
                password = User.objects.make_random_password()
                user = User.objects.create_user(
                    email=idinfo['email'],
                    username=idinfo['email'],
                    first_name=idinfo['given_name'],
                    last_name=idinfo['family_name'],
                    password=password)
                name = idinfo['email'].replace('@', '_').replace('.',
                                                                 '_') + '.png'
                response = requester.get(idinfo['picture'], stream=True)
                if response.status_code != requester.codes.ok:
                    lf = tempfile.NamedTemporaryFile()
                    for block in response.iter_content(1024 * 8):
                        if not block:
                            break
                        lf.write(block)
                    user.image.save(name, files.File(lf))

            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            serializer = UserRegisterSerializer(user)
            return Response({'token': token, 'user': serializer.data})
        except ValueError as err:
            # Invalid token
            content = {'message': err.__str__()}
            return Response(content, 500)
Ejemplo n.º 15
0
def check_bot_authenticity(token, audience):
    if not token:
        raise ValueError("Invalid token")

    if not audience:
        raise ValueError(f"Invalid audience")

    id_info = id_token.verify_token(
        token,
        requests.Request(),
        audience=audience,
        certs_url=PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER,
    )

    if id_info["iss"] != CHAT_ISSUER:
        raise ValueError("Wrong issuer")
Ejemplo n.º 16
0
def decode_token(token, audience=None) -> dict:
    """
    Decide the given Google OpenID token into JSON representation. If an
    audience is given, the token is verified against the provided audience.
    Otherwise, verification is not attempted

    :param token:
    :param audience:
    :return:
    """
    request = google.auth.transport.requests.Request()
    # https://github.com/googleapis/google-auth-library-python/blob/ca8d98ab2e5277e53ab8df78beb1e75cdf5321e3/google/oauth2/id_token.py#L109-L127
    return id_token.verify_token(token,
                                 request,
                                 audience=audience,
                                 certs_url=CERTS_URL)
Ejemplo n.º 17
0
def _validate_iap_jwt(iap_jwt, expected_audience):
    """Validate an IAP JWT.

    Args:
      iap_jwt: The contents of the X-Goog-IAP-JWT-Assertion header.
      expected_audience: The Signed Header JWT audience. See
          https://cloud.google.com/iap/docs/signed-headers-howto
          for details on how to get this value.

    Returns:
      (user_id, user_email).
    """

    decoded_jwt = id_token.verify_token(
        iap_jwt, requests.Request(), audience=expected_audience,
        certs_url='https://www.gstatic.com/iap/verify/public_key')
    return (decoded_jwt['sub'], decoded_jwt['email'])
Ejemplo n.º 18
0
def authenticate_openid(request, token):
    """Authenticate user using an OpenID token."""
    try:
        unverified_claims = jwt.decode(token, None, False)
    except Exception as exc:
        raise ParseError("Bad token: {}".format(str(exc)))

    # Validates token following recommendations at
    # https://developers.google.com/identity/protocols/oauth2/openid-connect#validatinganidtoken
    # Does basic validation before pinging Google to do token verification

    exp = unverified_claims.get("exp")
    if exp and float(exp) < time.time():
        raise ParseError("Token has expired")

    if unverified_claims.get("iss") != GOOGLE_ISS:
        raise ParseError("Invalid token issuer")

    if unverified_claims.get("aud") not in GOOGLE_AUDS:
        raise ParseError("Invalid token audience")

    transport = requests.Request()
    try:
        claims = id_token.verify_token(token, transport)
    except ValueError:
        raise ParseError("Token could not be verified")

    if not claims.get("email_verified"):
        raise ParseError("Email address has not been verified")

    email = claims.get("email")
    given_name = claims.get("given_name")
    family_name = claims.get("family_name")
    name = claims.get("name")
    if name is not None and given_name is None and family_name is None:
        given_name, family_name = name.split()[:1]
    try:
        user = User.objects.get(email=email)
    except ObjectDoesNotExist:
        username = generate_username(email, given_name, family_name)
        user = User.objects.create_user(
            username, email=email, first_name=given_name, last_name=family_name
        )

    return user
Ejemplo n.º 19
0
def _authenticate(token):
    if not token:
        return False

    try:
        result = id_token.verify_token(
            id_token=token.replace("Bearer ", ""),
            request=Request(),
            certs_url=os.environ["AUTH_CERTS_URL"],
        )
    except ValueError:
        return False

    return all((
        result["aud"] == os.environ["AUTH_AUDIENCE"],
        result["iss"] in os.environ["AUTH_ISSUER"].split(","),
        result["exp"] >= time.time(),
    ))
Ejemplo n.º 20
0
    def authenticate(self, request: Request) -> tuple:
        auth = get_authorization_header(request).decode()
        try:
            scheme, token = auth.split()
        except ValueError:
            exc = NotAuthenticatedException("Invalid Header.")
            exc.status_code = 401
            raise exc
        if not scheme == "Bearer":
            raise NotAuthenticatedException("Invalid scheme.")

        try:
            req = google.auth.transport.requests.Request()
            payload = id_token.verify_token(
                token, request=req
            )
            sub = payload["sub"]
            audience = payload["aud"]
        except KeyError:
            raise NotAuthenticatedException("Invalid validation payload.")
        except Exception:  # noqa E722
            raise NotAuthenticatedException("Invalid token.")

        if self.strict:
            from urllib.parse import urlparse
            request_result = urlparse(
                request._request.build_absolute_uri()  # noqa protected
            )
            audience_result = urlparse(audience)

            server_domain = request_result.netloc
            audience_domain = audience_result.netloc

            if audience_domain not in server_domain:
                raise NotAuthenticatedException("Invalid audience.")

        User = get_user_model()
        user = User.objects.filter(sub=sub).first()
        if not user or not user.is_active:
            raise NotAuthenticatedException("Invalid token.")

        return user, None
Ejemplo n.º 21
0
def validate_iap_jwt_and_get_email(iap_jwt, audience):
    """
    Validate an IAP JWT and return email
    Source: https://cloud.google.com/iap/docs/signed-headers-howto

    :param iap_jwt: The contents of the X-Goog-IAP-JWT-Assertion header.
    :param audience: The audience to validate against
    """

    try:
        decoded_jwt = id_token.verify_token(
            iap_jwt,
            requests.Request(),
            audience=audience,
            certs_url='https://www.gstatic.com/iap/verify/public_key',
        )
        return decoded_jwt['email']
    except Exception as e:
        logging.error(f'JWT validation error {e}')
        raise e
Ejemplo n.º 22
0
def validate_iap_jwt(iap_jwt, expected_audience):
    """Validate an IAP JWT.
    Args:
      iap_jwt: The contents of the X-Goog-IAP-JWT-Assertion header.
      expected_audience: The Signed Header JWT audience. See
          https://cloud.google.com/iap/docs/signed-headers-howto
          for details on how to get this value.
    Returns:
      (user_id, user_email, error_str).
    """

    try:
        decoded_jwt = id_token.verify_token(
            iap_jwt,
            requests.Request(),
            audience=expected_audience,
            certs_url='https://www.gstatic.com/iap/verify/public_key')
        return (decoded_jwt['sub'], decoded_jwt['email'], '')
    except Exception as e:
        return (None, None, '**ERROR: JWT validation error {}**'.format(e))
Ejemplo n.º 23
0
def verify_token(token: str, audience: str) -> dict:
    request = google.auth.transport.requests.Request()
    payload = id_token.verify_token(token, request=request, audience=audience)
    return payload
Ejemplo n.º 24
0
def verify_token(token: str, audience: str) -> dict:
    """Verify token signature and return the token payload"""
    request = google.auth.transport.requests.Request()
    payload = id_token.verify_token(token, request=request, audience=audience)
    return payload
Ejemplo n.º 25
0
audience = 'https://yourapp.appspot.com'
additional_claims = {'target_audience': 'http://yourappspot.com'}

svc_creds = service_account.Credentials.from_service_account_file(
    '/home/srashid/gcp_misc/certs/GCPNETAppID-e65deccae47b.json')
jwt_creds = jwt.Credentials.from_signing_credentials(
    svc_creds, audience=audience, additional_claims=additional_claims)

request = google.auth.transport.requests.Request()
jwt_creds.refresh(request)
idt = jwt_creds.token
print 'id_token: ' + idt
print id_token.verify_token(
    idt,
    request,
    certs_url=
    'https://www.googleapis.com/service_accounts/v1/metadata/x509/[email protected]'
)

print '--------------------------------------------------------------------------'

print "++++++++++++++  3. mint and verify google_id_token for a service_account ++++++++++++++++"
# "aud": "http://yourappspot.com",
# "iss": "https://accounts.google.com",

from google.oauth2 import id_token
from google.oauth2 import service_account
import json

audience = "https://www.googleapis.com/oauth2/v4/token"
additional_claims = {'target_audience': 'http://yourappspot.com'}
Ejemplo n.º 26
0
def google_auth():
    """
    Method to handle user signing in via Google.
    This method will either connect the user to their account in the database,
    or create a new account for them.
    """
    google_user_data = json.loads(request.get_data())

    try:
        token = google_user_data['token']
        idinfo = {}
        
         # Specify the CLIENT_ID of the app that accesses the backend:
        for client_id in CLIENT_IDS:
            try:
                idinfo = id_token.verify_token(token, requests.Request(), client_id)
                break
            except: pass
    
        # save information based on token
        user_email = idinfo['email']
        user_first = idinfo['given_name']
        user_last = idinfo['family_name']

    except:
        return 'Invalid token', 400
     
    user_query = {
        "email": google_user_data["email"]
    }
    
    # check that the user email is equivalent to the token
    if user_query['email'] != user_email:
    
        return 'Account does not match token', 400
    
    ip_addr = request.access_route[0]
    # get user agent
    user_agent = str(request.headers.get("User-Agent"))
    try:
        os_info = user_agent.split(')')[0].split('(')[1].strip()
    except:
        os_info = "Unknown"
    
    # protects against noSQL injection
    if not is_clean_email(user_query['email']):
    
        #return that user made invalid email
        return json.dumps({"success":False, "message": "email was not clean."}), 400, {"ContentType":"application/json"}
    
    #attempt to find user with information given
    google_user = grades_db.users.find_one(user_query)
    
    if google_user == None:
        """
        Options:  
            - here we can add a user to the database with no password, and 
            thus no one can access their account unless they sign in with their Google account

            - alternatively, we could redirect a user to a signup page on the frontend
            where they can enter a password
        """
        #save user information
        user = {
                "first_name": google_user_data["first_name"],
                "last_name": "",
                "email": google_user_data["email"],
                "hashed_pw":"",
                "wishlist": {},
                "os_info": [os_info],
                "ip_address_list": [ip_addr],
                "timestamp": get_current_time(),
                "location": get_location_info(ip_addr),
                "account_type": "Google"
            }
        
        try:
            user["last_name"] = google_user_data["last_name"]
        except:
            pass

        # check that user info is valid
        if not validate_analytics_auth(user):
            return json.dumps({"success":False}), 400, {"ContentType":"application/json"}

        #add user to db
        grades_db.users.insert_one(user)

        #send the user an email
        send_signup_email(google_user_data["first_name"], google_user_data["email"])

        #try to find existing user
        current_user = grades_db.users.find_one(user)

        #get user info
        user_info = get_user_token(current_user)
        user_info["type"] = "SignUp"

        # write calls to analytics for google signup
        analytics = add_analytics_auth("SignUp", "Google", google_user_data["email"], google_user_data["first_name"], google_user_data["last_name"], os_info, ip_addr)
        
        # if analytics was malicious, return false
        if not analytics:
            return json.dumps({"success":False}), 400, {"ContentType":'application/json'}

        #return that user was signed up
        return json.dumps(user_info), 200, {"ContentType":"application/json"}

    else:
        """
        Send user to their homepage
        """
        user_info = get_user_token(google_user)
        
        # ensure that os and ip are clean
        if not is_clean_query(os_info) or not is_clean_query(ip_addr):
        
            return json.dumps({"success":False, "message": "IP/OS was not clean."}), 400, {"ContentType":"application/json"}
        
        # update os and ip address in db
        update_os_ip(google_user, os_info, ip_addr)

        # write calls to analytics for google signup
        analytics = add_analytics_auth("Login", "Google", google_user_data["email"], google_user_data["first_name"], google_user_data["last_name"], os_info, ip_addr)
        
        # if analytics was malicious, return false
        if not analytics:
        
            return json.dumps({"success":False, "message": "Analytics was not clean."}), 400, {"ContentType":'application/json'}
        
        return json.dumps(user_info), 200,
        {'ContentType':'application/json'}


    return json.dumps({'success':False}), 404, {"ContentType":"application/json"}
Ejemplo n.º 27
0
def authenticate_openid(request: Request, token: str) -> User:
    """
    Authenticate user using an OpenID token.

    Currently only deals with tokens issued by Google.
    Validates token following recommendations at
    https://developers.google.com/identity/protocols/oauth2/openid-connect#validatinganidtoken
    Does basic validation before pinging Google to do token verification.

    If the verified email address matches an existing user then returns
    that user, otherwise creates a new user with the email as their primary email.
    """
    # Run some basic checks on the token
    try:
        unverified_claims = jwt.decode(token, "", False)
    except Exception as exc:
        raise ParseError("Bad token: {}".format(str(exc)))

    exp = unverified_claims.get("exp")
    if exp and float(exp) < time.time():
        raise ParseError("Token has expired")

    if unverified_claims.get("iss") != GOOGLE_ISS:
        raise ParseError("Invalid token issuer")

    if unverified_claims.get("aud") not in GOOGLE_AUDS:
        raise ParseError("Invalid token audience")

    # Verify the token with Google
    transport = requests.Request()
    try:
        claims = id_token.verify_token(token, transport)
    except ValueError:
        raise ParseError("Token could not be verified")

    if not claims.get("email_verified"):
        raise ParseError("Email address has not been verified")

    # Extract the verified data
    email = claims.get("email")
    given_name = claims.get("given_name", "")
    family_name = claims.get("family_name", "")
    name = claims.get("name")
    if name and not given_name and not family_name and len(name.split()) > 1:
        given_name, family_name = name.split()[:2]
    picture = claims.get("picture")

    # Check whether there is an existing user with this email address
    try:
        email_address = EmailAddress.objects.get(email__iexact=email)
        user = email_address.user
    except EmailAddress.DoesNotExist:
        try:
            user = User.objects.get(email__iexact=email)
        except User.DoesNotExist:
            user = None
        else:
            email_address = EmailAddress.objects.create(
                user=user, email=email, primary=True, verified=False
            )

    if user:
        # Check that the user's email is verified. This prevents an attacker
        # from stealing a users credentials by using their email address
        if not email_address.verified:
            confirmation = EmailConfirmation.create(email_address=email_address)
            confirmation.send()
            raise AuthenticationFailed(
                f"For security reasons, please verify your email address first; we have sent an email to {email}."
            )
    else:
        # Create a new user with a verified email address
        user = User.objects.create_user(
            username=generate_username(email, given_name, family_name),
            email=email,
            first_name=given_name,
            last_name=family_name,
        )
        EmailAddress.objects.create(user=user, email=email, verified=True, primary=True)

    # Update the user's image if one has not already been set
    if picture and user.personal_account.image_is_identicon():
        set_image_from_url.delay(user.personal_account.id, picture)

    return user
Ejemplo n.º 28
0
def process_key(message, context):
    if context:
        print("""This Function was triggered by messageId {} published at {}""".format(context.event_id,
                                                                                       context.timestamp))

    if CLOUD_FUNC_KEY_DATA in message:
        data = base64.b64decode(message[CLOUD_FUNC_KEY_DATA]).decode('utf-8')
        log(f"event dict data key has value: {data}", severity=LOG_SEVERITY_DEBUG)
    else:
        raise LookupError(f"event dict does not contain data key: {message}")

    SA_key_not_rotated = json.loads(data)
    key_resource = "resource"
    if key_resource not in SA_key_not_rotated:
        raise LookupError(f"Security command center finding dict does not contain key {key_resource}")

    resource = SA_key_not_rotated[key_resource]
    key_parentDisplayName = "parentDisplayName"
    if key_parentDisplayName not in resource:
        raise LookupError(f"Security command center finding dict does not contain key {key_parentDisplayName}")

    # extract SA from parentDisplayName
    project_SA_REGEX = 'projects/([\w-]+)/serviceAccounts/' + SA_regex
    parentDisplayName = resource[key_parentDisplayName]
    parentDisplayName_regex_search_result = re.search(project_SA_REGEX, parentDisplayName)
    if not parentDisplayName_regex_search_result or len(parentDisplayName_regex_search_result.groups()) != 2:
        raise ValueError(
            f"finding.{key_resource}.{key_parentDisplayName} failed to match regular expression {project_SA_REGEX}")

    GCP_SA = parentDisplayName_regex_search_result.group(2) + SA_postfix
    project_id = parentDisplayName_regex_search_result.group(1)
    log(f"extracted Google service account is {GCP_SA} and project ID is {project_id}", severity=LOG_SEVERITY_DEBUG)

    result = verify_config(GCP_SA, project_id, get_config_func=get_or_init_config)
    if result[key_abort_level] != 0:
        return result[key_payload]

    secret_project_id = result[key_payload][key_secret_project_id]

    # create an authenticated request to Cloud run GSA key manager for key rotation
    google_oauth_request = google.auth.transport.requests.Request()
    target_audience = result[key_payload][key_cloud_run_url]
    url = f"{result[key_payload][key_cloud_run_url]}/{result[key_payload][key_cloud_run_subpath]}"

    # local debugging vs executing in Google cloud
    if 'GCP_SA' in os.environ:
        creds = service_account.IDTokenCredentials.from_service_account_file(
            os.environ['GOOGLE_APPLICATION_CREDENTIALS'], target_audience=target_audience)
    else:
        creds = compute_engine.IDTokenCredentials(google_oauth_request,
                                                  target_audience=target_audience,
                                                  use_metadata_identity_endpoint=True)

    authed_session = AuthorizedSession(creds)
    form_data = {
        'GCP_SAs': GCP_SA,
        # 'secret_name_prefix': 'hil_0_',
        key_secret_project_id: secret_project_id
    }
    sa_key_manager_response = authed_session.request(result[key_payload][key_cloud_run_verb], url=url, data=form_data)

    func_response = {
        'content': sa_key_manager_response.content.decode('utf-8'),
        'reason': sa_key_manager_response.reason,
        'status_code': sa_key_manager_response.status_code,
    }

    # on success, response has json method
    if sa_key_manager_response.status_code == HTTPStatus.OK:
        func_response['content'] = sa_key_manager_response.json()

    # show security tokens at local debugging
    if 'GCP_SA' in os.environ:
        google_oauth_request = google.auth.transport.requests.Request()
        func_response['identity_token'] = creds.token
        func_response['Open ID Connect token verification'] = id_token.verify_token(creds.token,
                                                                                    google_oauth_request)
    else:
        log(f"Calling {result[key_payload][key_cloud_run_url]} returns: {json.dumps(func_response)}", severity='DEBUG')

    return func_response
Ejemplo n.º 29
0
    def authenticate(self, request):
        now = time.time()
        try:
            auth_header = request.headers['Authorization']
            if auth_header.startswith('Bearer '):
                bearer_token = auth_header[7:]
            else:
                msg = _(
                    f'Authorization header malformed. Expected Bearer: <token>; got {auth_header}'
                )
                logging.info(msg)
                raise exceptions.AuthenticationFailed(msg)
        except KeyError:
            msg = _('Invalid Authorization header. No credentials provided.')
            logging.info(msg)
            raise exceptions.AuthenticationFailed(msg)

        # verify our token
        auth_request = google.auth.transport.requests.Request()
        try:
            token = id_token.verify_token(
                bearer_token,
                auth_request,
                certs_url=GoogleOpenIDAuthentication.certs_url)
        except ValueError as e:
            error_message = getattr(e, 'message', str(e))
            msg = _(
                f'Authentication failed. Could not verify token; err = {error_message}.'
            )
            logging.error(msg)
            raise exceptions.AuthenticationFailed(msg)
        # ensure that it has the desired claims
        if not all([
                key in token for key in
            ['aud', 'iss', 'email', 'email_verified', 'iat', 'exp', 'sub']
        ]):
            msg = _(
                'Authentication failed. Token did not contain all required claims.'
            )
            logging.info(msg)
            raise exceptions.AuthenticationFailed(msg)
        token = SimpleNamespace(**token)
        logging.debug(f'Access attempted with token: {token}')
        # the audience indicated in the token should be the visited URL
        __, token_audience, __ = uri_breakdown(token.aud)
        __, required_audience, __ = uri_breakdown(request.build_absolute_uri())
        if token_audience != required_audience:
            msg = _(
                f'Authentication failed. Audience {token.aud} did not match auth endpoint {required_audience}.'
            )
            logging.info(msg)
            raise exceptions.AuthenticationFailed(msg)
        if not token.iat < now < token.exp:
            msg = _(f'Authentication failed. Token outside of valid window. '
                    f'Issued {token.iat}, Expires: {token.exp}, Now: {now}')
            logging.info(msg)
            raise exceptions.AuthenticationFailed(msg)
        try:
            user = User.objects.get(email__iexact=token.email)
        except User.DoesNotExist:
            msg = _(f'Authentication failed. No user with email {token.email}')
            logging.info(msg)
            raise exceptions.AuthenticationFailed(msg)

        return user, None
Ejemplo n.º 30
0
def VerifyIDToken(token, certs_url,  audience=None):
   request = google.auth.transport.requests.Request()
   result = id_token.verify_token(token,request,certs_url=certs_url)
   if audience in result['aud']:
     return True
   return False