Esempio n. 1
0
  def test_authenticate_with_expired_auth_token(self):
    url = get_url(IntegrationTest._JWKS_PATH)
    self._provider_ids[self._ISSUER] = self._PROVIDER_ID
    self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(False,
                                                                       url)
    IntegrationTest._mock_timer.return_value = 0

    # Create an auth token that expires in 10 seconds.
    jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS)
    jwt_claims["exp"] = time.time() + 10
    auth_token = token_utils.generate_auth_token(jwt_claims,
                                                 IntegrationTest._jwks._keys,
                                                 alg="RS256",
                                                 kid=IntegrationTest._rsa_key.kid)

    # Verify that the auth token can be authenticated successfully.
    self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                     self._auth_info,
                                     IntegrationTest._SERVICE_NAME)

    # Advance the timer by 20 seconds and make sure the token is expired.
    IntegrationTest._mock_timer.return_value += 20
    message = "The auth token has already expired"
    with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
      self._authenticator.authenticate(auth_token, self._auth_info,
                                       IntegrationTest._SERVICE_NAME)
Esempio n. 2
0
    def test_authenticate_with_expired_auth_token(self):
        url = get_url(IntegrationTest._JWKS_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        IntegrationTest._mock_timer.return_value = 0

        # Create an auth token that expires in 10 seconds.
        jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS)
        jwt_claims[u"exp"] = time.time() + 10
        auth_token = token_utils.generate_auth_token(
            jwt_claims,
            IntegrationTest._jwks._keys,
            alg=u"RS256",
            kid=IntegrationTest._rsa_key.kid)

        # Verify that the auth token can be authenticated successfully.
        self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                         self._auth_info,
                                         IntegrationTest._SERVICE_NAME)

        # Advance the timer by 20 seconds and make sure the token is expired.
        IntegrationTest._mock_timer.return_value += 20
        message = u"The auth token has already expired"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(auth_token, self._auth_info,
                                             IntegrationTest._SERVICE_NAME)
Esempio n. 3
0
 def assert_missing_claim_raise_exception(claim_name):
   jwt_claims = copy.deepcopy(self._jwt_claims)
   del jwt_claims[claim_name]
   auth_token = token_utils.generate_auth_token(jwt_claims,
                                                self._jwks._keys,
                                    kid=self._ec_kid)
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                'Missing "%s" claim' % claim_name):
     self._authenticator.get_jwt_claims(auth_token)
Esempio n. 4
0
 def test_authenticate_with_nbf_claim(self):
   # Set the "nbf" claim to some time in the future.
   self._jwt_claims["nbf"] = long(time.time() + 5)
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys)
   message = 'Current time is less than the "nbf" time'
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
     self._authenticator.authenticate(auth_token, self._method_info,
                                      "service.name")
Esempio n. 5
0
 def assert_missing_claim_raise_exception(claim_name):
     jwt_claims = copy.deepcopy(self._jwt_claims)
     del jwt_claims[claim_name]
     auth_token = token_utils.generate_auth_token(jwt_claims,
                                                  self._jwks._keys,
                                      kid=self._ec_kid)
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                  u'Missing "%s" claim' % claim_name):
         self._authenticator.get_jwt_claims(auth_token)
Esempio n. 6
0
 def assert_malformed_time_claim_raises_exception(claim_name, expiration):
     jwt_claims = copy.deepcopy(self._jwt_claims)
     jwt_claims[claim_name] = expiration
     auth_token = token_utils.generate_auth_token(jwt_claims,
                                                  self._jwks._keys)
     message = u'Malformed claim: "%s" must be an integer' % claim_name
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
         self._authenticator.authenticate(auth_token, self._method_info,
                                          u"service.name")
Esempio n. 7
0
 def assert_malformed_time_claim_raises_exception(claim_name, expiration):
   jwt_claims = copy.deepcopy(self._jwt_claims)
   jwt_claims[claim_name] = expiration
   auth_token = token_utils.generate_auth_token(jwt_claims,
                                                self._jwks._keys)
   message = 'Malformed claim: "%s" must be an integer' % claim_name
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
     self._authenticator.authenticate(auth_token, self._method_info,
                                      "service.name")
Esempio n. 8
0
 def test_authenticate_with_nbf_claim(self):
     # Set the "nbf" claim to some time in the future.
     self._jwt_claims[u"nbf"] = long(time.time() + 5)
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys)
     message = u'Current time is less than the "nbf" time'
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
         self._authenticator.authenticate(auth_token, self._method_info,
                                          u"service.name")
Esempio n. 9
0
 def test_authenticate_with_expired_auth_token(self):
   self._jwt_claims["exp"] = long(time.time() - 10)
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys)
   message = "The auth token has already expired"
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
     self._authenticator.authenticate(auth_token,
                                      self._method_info,
                                      "service.name")
Esempio n. 10
0
 def test_authenticate_with_expired_auth_token(self):
     self._jwt_claims[u"exp"] = long(time.time() - 10)
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys)
     message = u"The auth token has already expired"
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
         self._authenticator.authenticate(auth_token,
                                          self._method_info,
                                          u"service.name")
Esempio n. 11
0
 def test_authenticate_with_disallowed_audiences(self):
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys,
                                                kid=self._ec_kid)
   self._method_info.get_allowed_audiences.return_value = []
   self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "project-id"
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                "Audiences not allowed"):
     self._authenticator.authenticate(auth_token, self._method_info,
                                      self._service_name)
Esempio n. 12
0
 def test_authenticate_with_disallowed_audiences(self):
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys,
                                                  kid=self._ec_kid)
     self._method_info.get_allowed_audiences.return_value = []
     self._issuers_to_provider_ids[self._jwt_claims[u"iss"]] = u"project-id"
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                  u"Audiences not allowed"):
         self._authenticator.authenticate(auth_token, self._method_info,
                                          self._service_name)
Esempio n. 13
0
 def test_authenticate_with_single_audience(self):
   aud = "first.aud.com"
   self._jwt_claims["aud"] = aud
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys,
                                                kid=self._ec_kid)
   self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id"
   actual_user_info = self._authenticator.authenticate(auth_token,
                                                       self._method_info, aud)
   self.assertEqual([aud], actual_user_info.audiences)
Esempio n. 14
0
 def test_authenticate_with_single_audience(self):
     aud = u"first.aud.com"
     self._jwt_claims[u"aud"] = aud
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys,
                                                  kid=self._ec_kid)
     self._issuers_to_provider_ids[self._jwt_claims[u"iss"]] = u"provider-id"
     actual_user_info = self._authenticator.authenticate(auth_token,
                                                         self._method_info, aud)
     self.assertEqual([aud], actual_user_info.audiences)
Esempio n. 15
0
 def test_authenticate_with_disallowed_provider_id(self):
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys,
                                    kid=self._ec_kid)
   self._method_info.is_provider_allowed.return_value = False
   self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "id"
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                "The requested method does not allow provider "
                                "id: id"):
     self._authenticator.authenticate(auth_token, self._method_info,
                                      self._service_name)
Esempio n. 16
0
 def test_authenticate_with_disallowed_provider_id(self):
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys,
                                      kid=self._ec_kid)
     self._method_info.is_provider_allowed.return_value = False
     self._issuers_to_provider_ids[self._jwt_claims[u"iss"]] = u"id"
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                  u"The requested method does not allow provider "
                                  u"id: id"):
         self._authenticator.authenticate(auth_token, self._method_info,
                                          self._service_name)
Esempio n. 17
0
 def test_authenticate_successfully(self):
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys,
                                                  kid=self._ec_kid)
     self._method_info.get_allowed_audiences.return_value = ["first.com"]
     self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id"
     actual_user_info = self._authenticator.authenticate(
         auth_token, self._method_info, "service.name.com")
     self.assert_user_info(actual_user_info, self._jwt_claims["aud"],
                           self._jwt_claims["email"],
                           self._jwt_claims["sub"], self._jwt_claims["iss"])
Esempio n. 18
0
 def test_authenticate_with_service_name_as_audience(self):
     self._jwt_claims["aud"].append(self._service_name)
     self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id"
     self._method_info.get_allowed_audiences.return_value = []
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys,
                                                  kid=self._ec_kid)
     actual_user_info = self._authenticator.authenticate(
         auth_token, self._method_info, self._service_name)
     self.assert_user_info(actual_user_info, self._jwt_claims["aud"],
                           self._jwt_claims["email"],
                           self._jwt_claims["sub"], self._jwt_claims["iss"])
Esempio n. 19
0
 def test_authenticate_successfully(self):
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys,
                                                kid=self._ec_kid)
   self._method_info.get_allowed_audiences.return_value = ["first.com"]
   self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id"
   actual_user_info = self._authenticator.authenticate(auth_token,
                                                       self._method_info,
                                                       "service.name.com")
   self.assert_user_info(actual_user_info, self._jwt_claims["aud"],
                         self._jwt_claims["email"], self._jwt_claims["sub"],
                         self._jwt_claims["iss"])
    def test_auth_token_cache_capacity(self):
        authenticator = tokens.Authenticator({},
                                             self._jwks_supplier,
                                             cache_capacity=2)

        self._jwt_claims[u"email"] = u"*****@*****.**"
        auth_token1 = token_utils.generate_auth_token(self._jwt_claims,
                                                      self._jwks._keys)
        self._jwt_claims[u"email"] = u"*****@*****.**"
        auth_token2 = token_utils.generate_auth_token(self._jwt_claims,
                                                      self._jwks._keys)

        # Populate the decoded result into cache.
        authenticator.get_jwt_claims(auth_token1)
        authenticator.get_jwt_claims(auth_token2)

        # Reset the returned JWKS so the signature verification will fail next
        # time.
        new_ec_jwk = jwk.ECKey(use=u"sig").load_key(ecc.P256)
        new_ec_jwk.kid = self._ec_kid
        new_jwks = jwk.KEYS()
        new_jwks._keys.append(new_ec_jwk)
        self._jwks_supplier.supply.return_value = new_jwks

        # Verify the following calls still succeed since the auth tokens are
        # cached.
        authenticator.get_jwt_claims(auth_token1)
        authenticator.get_jwt_claims(auth_token2)

        # Populate a third auth token into the cache.
        self._jwt_claims[u"email"] = u"*****@*****.**"
        auth_token3 = token_utils.generate_auth_token(self._jwt_claims,
                                                      new_jwks._keys)
        authenticator.get_jwt_claims(auth_token3)

        # Make sure the first auth token is evicted from the cache since the cache
        # is full.
        with self.assertRaises(suppliers.UnauthenticatedException):
            authenticator.get_jwt_claims(auth_token1)
Esempio n. 21
0
 def test_authenticate_with_service_name_as_audience(self):
   self._jwt_claims["aud"].append(self._service_name)
   self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id"
   self._method_info.get_allowed_audiences.return_value = []
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys,
                                    kid=self._ec_kid)
   actual_user_info = self._authenticator.authenticate(auth_token,
                                                       self._method_info,
                                                       self._service_name)
   self.assert_user_info(actual_user_info, self._jwt_claims["aud"],
                         self._jwt_claims["email"], self._jwt_claims["sub"],
                         self._jwt_claims["iss"])
Esempio n. 22
0
    def test_verify_fails(self):
        auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                     self._jwks._keys,
                                         kid=self._ec_kid)

        # Let the _jwks_supplier return a different key than the one we use to sign
        # the JWT.
        new_jwk = jwk.ECKey(use=u"sig").load_key(ecc.P256)
        new_jwks = jwk.KEYS()
        new_jwks._keys.append(new_jwk)
        self._jwks_supplier.supply.return_value = new_jwks

        with self.assertRaises(suppliers.UnauthenticatedException):
            self._authenticator.get_jwt_claims(auth_token)
Esempio n. 23
0
  def test_verify_fails(self):
    auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                 self._jwks._keys,
                                     kid=self._ec_kid)

    # Let the _jwks_supplier return a different key than the one we use to sign
    # the JWT.
    new_jwk = jwk.ECKey(use="sig").load_key(ecc.P256)
    new_jwks = jwk.KEYS()
    new_jwks._keys.append(new_jwk)
    self._jwks_supplier.supply.return_value = new_jwks

    with self.assertRaises(suppliers.UnauthenticatedException):
      self._authenticator.get_jwt_claims(auth_token)
Esempio n. 24
0
  def test_auth_token_cache_capacity(self):
    authenticator = tokens.Authenticator({}, self._jwks_supplier, cache_capacity=2)

    self._jwt_claims["email"] = "*****@*****.**"
    auth_token1 = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys)
    self._jwt_claims["email"] = "*****@*****.**"
    auth_token2 = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys)

    # Populate the decoded result into cache.
    authenticator.get_jwt_claims(auth_token1)
    authenticator.get_jwt_claims(auth_token2)

    # Reset the returned JWKS so the signature verification will fail next
    # time.
    new_ec_jwk = jwk.ECKey(use="sig").load_key(ecc.P256)
    new_ec_jwk.kid = self._ec_kid
    new_jwks = jwk.KEYS()
    new_jwks._keys.append(new_ec_jwk)
    self._jwks_supplier.supply.return_value = new_jwks

    # Verify the following calls still succeed since the auth tokens are
    # cached.
    authenticator.get_jwt_claims(auth_token1)
    authenticator.get_jwt_claims(auth_token2)

    # Populate a third auth token into the cache.
    self._jwt_claims["email"] = "*****@*****.**"
    auth_token3 = token_utils.generate_auth_token(self._jwt_claims,
                                                  new_jwks._keys)
    authenticator.get_jwt_claims(auth_token3)

    # Make sure the first auth token is evicted from the cache since the cache
    # is full.
    with self.assertRaises(suppliers.UnauthenticatedException):
      authenticator.get_jwt_claims(auth_token1)
Esempio n. 25
0
  def test_invalid_openid_discovery_url(self):
    issuer = "https://invalid.issuer"
    self._provider_ids[self._ISSUER] = self._PROVIDER_ID
    self._configs[issuer] = suppliers.IssuerUriConfig(True, None)

    jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS)
    jwt_claims["iss"] = issuer
    auth_token = token_utils.generate_auth_token(jwt_claims,
                                                 IntegrationTest._jwks._keys,
                                                 alg="RS256",
                                                 kid=IntegrationTest._rsa_key.kid)
    message = "Cannot discover the jwks uri"
    with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
      self._authenticator.authenticate(auth_token, self._auth_info,
                                       IntegrationTest._SERVICE_NAME)
Esempio n. 26
0
 def test_authenticate_auth_token_with_bad_signature(self):
   new_rsa_key = jwk.RSAKey(use="sig").load_key(PublicKey.RSA.generate(2048))
   kid = IntegrationTest._rsa_key.kid
   new_rsa_key.kid = kid
   new_jwks = jwk.KEYS()
   new_jwks._keys.append(new_rsa_key)
   auth_token = token_utils.generate_auth_token(IntegrationTest._JWT_CLAIMS,
                                                new_jwks._keys, alg="RS256",
                                                kid=kid)
   url = get_url(IntegrationTest._JWKS_PATH)
   self._provider_ids[self._ISSUER] = self._PROVIDER_ID
   self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(False,
                                                                      url)
   message = "Signature verification failed"
   with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message):
     self._authenticator.authenticate(auth_token, self._auth_info,
                                      IntegrationTest._SERVICE_NAME)
Esempio n. 27
0
    def test_invalid_openid_discovery_url(self):
        issuer = u"https://invalid.issuer"
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[issuer] = suppliers.IssuerUriConfig(True, None)

        jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS)
        jwt_claims[u"iss"] = issuer
        auth_token = token_utils.generate_auth_token(
            jwt_claims,
            IntegrationTest._jwks._keys,
            alg=u"RS256",
            kid=IntegrationTest._rsa_key.kid)
        message = u"Cannot discover the jwks uri"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(auth_token, self._auth_info,
                                             IntegrationTest._SERVICE_NAME)
Esempio n. 28
0
 def test_authenticate_auth_token_with_bad_signature(self):
     new_rsa_key = jwk.RSAKey(use=u"sig").load_key(
         PublicKey.RSA.generate(2048))
     kid = IntegrationTest._rsa_key.kid
     new_rsa_key.kid = kid
     new_jwks = jwk.KEYS()
     new_jwks._keys.append(new_rsa_key)
     auth_token = token_utils.generate_auth_token(
         IntegrationTest._JWT_CLAIMS, new_jwks._keys, alg=u"RS256", kid=kid)
     url = get_url(IntegrationTest._JWKS_PATH)
     self._provider_ids[self._ISSUER] = self._PROVIDER_ID
     self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
         False, url)
     message = u"Signature verification failed"
     with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                  message):
         self._authenticator.authenticate(auth_token, self._auth_info,
                                          IntegrationTest._SERVICE_NAME)
Esempio n. 29
0
  def test_get_jwt_claims_via_caching(self):
    AuthenticatorTest._mock_timer.return_value = 10

    auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                 self._jwks._keys)
    # Populate the decoded result into cache.
    self._authenticator.get_jwt_claims(auth_token)

    # Reset the returned JWKS so the signature verification will fail next
    # time.
    self._jwks_supplier.supply.return_value = jwk.KEYS()

    # Forword time by 10 seconds.
    AuthenticatorTest._mock_timer.return_value += 10
    # This call should succeed since the auth_token is cached.
    self._authenticator.get_jwt_claims(auth_token)

    # Forword time by 5 minutes.
    AuthenticatorTest._mock_timer.return_value += 5 * 60
    # This call should fail since the cache expires and it needs to re-decode
    # the auth token with a different key set.
    with self.assertRaises(suppliers.UnauthenticatedException):
      self._authenticator.get_jwt_claims(auth_token)
Esempio n. 30
0
    def test_get_jwt_claims_via_caching(self):
        AuthenticatorTest._mock_timer.return_value = 10

        auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                     self._jwks._keys)
        # Populate the decoded result into cache.
        self._authenticator.get_jwt_claims(auth_token)

        # Reset the returned JWKS so the signature verification will fail next
        # time.
        self._jwks_supplier.supply.return_value = jwk.KEYS()

        # Forword time by 10 seconds.
        AuthenticatorTest._mock_timer.return_value += 10
        # This call should succeed since the auth_token is cached.
        self._authenticator.get_jwt_claims(auth_token)

        # Forword time by 5 minutes.
        AuthenticatorTest._mock_timer.return_value += 5 * 60
        # This call should fail since the cache expires and it needs to re-decode
        # the auth token with a different key set.
        with self.assertRaises(suppliers.UnauthenticatedException):
            self._authenticator.get_jwt_claims(auth_token)
Esempio n. 31
0
class IntegrationTest(unittest.TestCase):

    _CURRENT_TIME = int(time.time())
    _PORT = 8080
    _ISSUER = u"https://*****:*****@name.com"
    _X509_PATH = u"x509"

    _JWT_CLAIMS = {
        u"aud": [u"https://aud1.local.host", u"https://aud2.local.host"],
        u"exp": _CURRENT_TIME + 60,
        u"email": u"*****@*****.**",
        u"iss": _ISSUER,
        u"sub": u"subject-id"
    }

    _ec_jwk = jwk.ECKey(use=u"sig").load_key(ecc.P256)
    _rsa_key = jwk.RSAKey(use=u"sig").load_key(PublicKey.RSA.generate(1024))

    _ec_jwk.kid = u"ec-key-id"
    _rsa_key.kid = u"rsa-key-id"

    _mock_timer = mock.MagicMock()

    _jwks = jwk.KEYS()
    _jwks._keys.append(_ec_jwk)
    _jwks._keys.append(_rsa_key)

    _AUTH_TOKEN = token_utils.generate_auth_token(_JWT_CLAIMS,
                                                  _jwks._keys,
                                                  alg=u"RS256",
                                                  kid=_rsa_key.kid)

    @classmethod
    def setUpClass(cls):
        dirname = os.path.dirname(os.path.realpath(__file__))
        cls._cert_file = os.path.join(dirname, u"ssl.cert")
        cls._key_file = os.path.join(dirname, u"ssl.key")
        os.environ[u"REQUESTS_CA_BUNDLE"] = cls._cert_file

        rest_server = cls._RestServer()
        rest_server.start()

    def setUp(self):
        self._provider_ids = {}
        self._configs = {}
        self._authenticator = auth.create_authenticator(
            self._provider_ids, self._configs)

        self._auth_info = mock.MagicMock()
        self._auth_info.is_provider_allowed.return_value = True
        self._auth_info.get_allowed_audiences.return_value = [
            u"https://aud1.local.host"
        ]

    def test_verify_auth_token_with_jwks(self):
        url = get_url(IntegrationTest._JWKS_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        user_info = self._authenticator.authenticate(
            IntegrationTest._AUTH_TOKEN, self._auth_info,
            IntegrationTest._SERVICE_NAME)
        self._assert_user_info_equals(
            tokens.UserInfo(IntegrationTest._JWT_CLAIMS), user_info)

    def test_authenticate_auth_token_with_bad_signature(self):
        new_rsa_key = jwk.RSAKey(use=u"sig").load_key(
            PublicKey.RSA.generate(2048))
        kid = IntegrationTest._rsa_key.kid
        new_rsa_key.kid = kid
        new_jwks = jwk.KEYS()
        new_jwks._keys.append(new_rsa_key)
        auth_token = token_utils.generate_auth_token(
            IntegrationTest._JWT_CLAIMS, new_jwks._keys, alg=u"RS256", kid=kid)
        url = get_url(IntegrationTest._JWKS_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        message = u"Signature verification failed"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(auth_token, self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_verify_auth_token_with_x509(self):
        url = get_url(IntegrationTest._X509_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        user_info = self._authenticator.authenticate(
            IntegrationTest._AUTH_TOKEN, self._auth_info,
            IntegrationTest._SERVICE_NAME)
        self._assert_user_info_equals(
            tokens.UserInfo(IntegrationTest._JWT_CLAIMS), user_info)

    def test_verify_auth_token_with_invalid_x509(self):
        url = get_url(IntegrationTest._INVALID_X509_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        message = u"Cannot load X.509 certificate"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_openid_discovery(self):
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            True, None)
        user_info = self._authenticator.authenticate(
            IntegrationTest._AUTH_TOKEN, self._auth_info,
            IntegrationTest._SERVICE_NAME)
        self._assert_user_info_equals(
            tokens.UserInfo(IntegrationTest._JWT_CLAIMS), user_info)

    def test_openid_discovery_failed(self):
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, None)
        message = (u"Cannot find the `jwks_uri` for issuer %s" %
                   IntegrationTest._ISSUER)
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_authenticate_with_malformed_auth_code(self):
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     u"Cannot decode the auth token"):
            self._authenticator.authenticate(u"invalid-auth-code",
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_authenticate_with_disallowed_issuer(self):
        url = get_url(IntegrationTest._JWKS_PATH)
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        message = u"Unknown issuer: " + self._ISSUER
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_authenticate_with_unknown_issuer(self):
        message = (u"Cannot find the `jwks_uri` for issuer %s: "
                   u"either the issuer is unknown") % IntegrationTest._ISSUER
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_authenticate_with_invalid_audience(self):
        url = get_url(IntegrationTest._JWKS_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        self._auth_info.get_allowed_audiences.return_value = []
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     u"Audiences not allowed"):
            self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    @mock.patch(u"time.time", _mock_timer)
    def test_authenticate_with_expired_auth_token(self):
        url = get_url(IntegrationTest._JWKS_PATH)
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        IntegrationTest._mock_timer.return_value = 0

        # Create an auth token that expires in 10 seconds.
        jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS)
        jwt_claims[u"exp"] = time.time() + 10
        auth_token = token_utils.generate_auth_token(
            jwt_claims,
            IntegrationTest._jwks._keys,
            alg=u"RS256",
            kid=IntegrationTest._rsa_key.kid)

        # Verify that the auth token can be authenticated successfully.
        self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                         self._auth_info,
                                         IntegrationTest._SERVICE_NAME)

        # Advance the timer by 20 seconds and make sure the token is expired.
        IntegrationTest._mock_timer.return_value += 20
        message = u"The auth token has already expired"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(auth_token, self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_invalid_openid_discovery_url(self):
        issuer = u"https://invalid.issuer"
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[issuer] = suppliers.IssuerUriConfig(True, None)

        jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS)
        jwt_claims[u"iss"] = issuer
        auth_token = token_utils.generate_auth_token(
            jwt_claims,
            IntegrationTest._jwks._keys,
            alg=u"RS256",
            kid=IntegrationTest._rsa_key.kid)
        message = u"Cannot discover the jwks uri"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(auth_token, self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def test_invalid_jwks_uri(self):
        url = u"https://invalid.jwks.uri"
        self._provider_ids[self._ISSUER] = self._PROVIDER_ID
        self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(
            False, url)
        message = u"Cannot retrieve valid verification keys from the `jwks_uri`"
        with self.assertRaisesRegexp(suppliers.UnauthenticatedException,
                                     message):
            self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN,
                                             self._auth_info,
                                             IntegrationTest._SERVICE_NAME)

    def _assert_user_info_equals(self, expected, actual):
        self.assertEqual(expected.audiences, actual.audiences)
        self.assertEqual(expected.email, actual.email)
        self.assertEqual(expected.subject_id, actual.subject_id)
        self.assertEqual(expected.issuer, actual.issuer)

    class _RestServer(object):
        def __init__(self):
            app = flask.Flask(u"integration-test-server")

            @app.route(u"/" + IntegrationTest._JWKS_PATH)
            def get_json_web_key_set():  # pylint: disable=unused-variable
                return IntegrationTest._jwks.dump_jwks()

            @app.route(u"/" + IntegrationTest._X509_PATH)
            def get_x509_certificates():  # pylint: disable=unused-variable
                cert = IntegrationTest._rsa_key.key.publickey().exportKey(
                    u"PEM")
                return flask.jsonify(
                    {IntegrationTest._rsa_key.kid: cert.decode('ascii')})

            @app.route(u"/" + IntegrationTest._INVALID_X509_PATH)
            def get_invalid_x509_certificates():  # pylint: disable=unused-variable
                return flask.jsonify(
                    {IntegrationTest._rsa_key.kid: u"invalid cert"})

            @app.route(u"/.well-known/openid-configuration")
            def get_openid_configuration():  # pylint: disable=unused-variable
                return flask.jsonify(
                    {u"jwks_uri": get_url(IntegrationTest._JWKS_PATH)})

            self._application = app

        def start(self):
            def run_app():
                ssl_context = (IntegrationTest._cert_file,
                               IntegrationTest._key_file)
                self._application.run(port=IntegrationTest._PORT,
                                      ssl_context=ssl_context)

            thread = threading.Thread(target=run_app, args=())
            thread.daemon = True
            thread.start()
Esempio n. 32
0
 def test_get_jwt_claims_without_kid(self):
     auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                  self._jwks._keys)
     actual_jwt_claims = self._authenticator.get_jwt_claims(auth_token)
     self.assertEqual(self._jwt_claims, actual_jwt_claims)
Esempio n. 33
0
 def test_get_jwt_claims_without_kid(self):
   auth_token = token_utils.generate_auth_token(self._jwt_claims,
                                                self._jwks._keys)
   actual_jwt_claims = self._authenticator.get_jwt_claims(auth_token)
   self.assertEqual(self._jwt_claims, actual_jwt_claims)