예제 #1
0
def _check_jwt_claims(jwt_claims):
    """Checks whether the JWT claims should be accepted.

    Specifically, this method checks the "exp" claim and the "nbf" claim (if
    present), and raises UnauthenticatedException if 1) the current time is
    before the time identified by the "nbf" claim, or 2) the current time is
    equal to or after the time identified by the "exp" claim.

    Args:
      jwt_claims: the JWT claims whose expiratio to be checked.

    Raises:
      UnauthenticatedException: When the "exp" claim is malformed or the JWT has
        already expired.
    """
    current_time = time.time()

    expiration = jwt_claims["exp"]
    if not isinstance(expiration, (int, long)):
        raise suppliers.UnauthenticatedException(
            'Malformed claim: "exp" must be an integer')
    if current_time >= expiration:
        raise suppliers.UnauthenticatedException(
            "The auth token has already expired")

    if "nbf" not in jwt_claims:
        return

    not_before_time = jwt_claims["nbf"]
    if not isinstance(not_before_time, (int, long)):
        raise suppliers.UnauthenticatedException(
            'Malformed claim: "nbf" must be an integer')
    if current_time < not_before_time:
        raise suppliers.UnauthenticatedException(
            'Current time is less than the "nbf" time')
예제 #2
0
    def authenticate(self, auth_token, auth_info, service_name):
        """Authenticates the current auth token.

        Args:
          auth_token: the auth token.
          auth_info: the auth configurations of the API method being called.
          service_name: the name of this service.

        Returns:
          A constructed UserInfo object representing the identity of the caller.

        Raises:
          UnauthenticatedException: When
            * the issuer is not allowed;
            * the audiences are not allowed;
            * the auth token has already expired.
        """
        try:
            jwt_claims = self.get_jwt_claims(auth_token)
        except Exception as error:
            raise suppliers.UnauthenticatedException(
                "Cannot decode the auth token", error)
        _check_jwt_claims(jwt_claims)

        user_info = UserInfo(jwt_claims)

        issuer = user_info.issuer
        if issuer not in self._issuers_to_provider_ids:
            raise suppliers.UnauthenticatedException("Unknown issuer: " +
                                                     issuer)
        provider_id = self._issuers_to_provider_ids[issuer]

        if not auth_info.is_provider_allowed(provider_id):
            raise suppliers.UnauthenticatedException(
                "The requested method does not "
                "allow provider id: " + provider_id)

        # Check the audiences decoded from the auth token. The auth token is
        # allowed when 1) an audience is equal to the service name, or 2) at least
        # one audience is allowed in the method configuration.
        audiences = user_info.audiences
        has_service_name = service_name in audiences

        allowed_audiences = auth_info.get_allowed_audiences(provider_id)
        intersected_audiences = set(allowed_audiences).intersection(audiences)
        if not has_service_name and not intersected_audiences:
            raise suppliers.UnauthenticatedException("Audiences not allowed")

        return user_info
예제 #3
0
 def test_malformed_authorization_header(self):
     auth_app = AuthMiddleware(self.UserInfoWsgiApp(),
                               self._mock_authenticator)
     environ = {
         "HTTP_AUTHORIZATION": "malformed-auth-token",
         wsgi.EnvironmentMiddleware.METHOD_INFO: mock.MagicMock(),
         wsgi.EnvironmentMiddleware.SERVICE_NAME: "service-name"
     }
     self._mock_authenticator.authenticate.side_effect = suppliers.UnauthenticatedException(
     )
     self.assertIsNone(auth_app(environ, _dummy_start_response))
예제 #4
0
        def _decode_and_verify():
            jwt_claims = jwt.JWT().unpack(auth_token).payload()
            _verify_required_claims_exist(jwt_claims)

            issuer = jwt_claims["iss"]
            keys = self._jwks_supplier.supply(issuer)
            try:
                return jws.JWS().verify_compact(auth_token, keys)
            except (jwkest.BadSignature, jws.NoSuitableSigningKeys,
                    jws.SignerAlgError) as exception:
                raise suppliers.UnauthenticatedException(
                    "Signature verification failed", exception)
예제 #5
0
def _verify_required_claims_exist(jwt_claims):
    """Verifies that the required claims exist.

    Args:
      jwt_claims: the JWT claims to be verified.

    Raises:
      UnauthenticatedException: if some claim doesn't exist.
    """
    for claim_name in ["aud", "exp", "iss", "sub"]:
        if claim_name not in jwt_claims:
            raise suppliers.UnauthenticatedException('Missing "%s" claim' %
                                                     claim_name)