def test_get_access_token_no_claims(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        token_info = self.jwt.get_access_token()
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token,
            {'key': datafile('public_cert.pem')}, audience=self.url)
        self.assertEqual(payload['iss'], self.service_account_email)
        self.assertEqual(payload['sub'], self.service_account_email)
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(token_info.expires_in, T1_EXPIRY - T1)

        # Verify that we vend the same token after 100 seconds
        utcnow.return_value = T2_DATE
        token_info = self.jwt.get_access_token()
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token,
            {'key': datafile('public_cert.pem')}, audience=self.url)
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(token_info.expires_in, T1_EXPIRY - T2)

        # Verify that we vend a new token after _MAX_TOKEN_LIFETIME_SECS
        utcnow.return_value = T3_DATE
        time.return_value = T3
        token_info = self.jwt.get_access_token()
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token,
            {'key': datafile('public_cert.pem')}, audience=self.url)
        expires_in = token_info.expires_in
        self.assertEqual(payload['iat'], T3)
        self.assertEqual(payload['exp'], T3_EXPIRY)
        self.assertEqual(expires_in, T3_EXPIRY - T3)
Beispiel #2
0
    def test_get_access_token_no_claims(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        token_info = self.jwt.get_access_token()
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token, {'key': datafile('public_cert.pem')},
            audience=self.url)
        self.assertEqual(payload['iss'], self.service_account_email)
        self.assertEqual(payload['sub'], self.service_account_email)
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(token_info.expires_in, T1_EXPIRY - T1)

        # Verify that we vend the same token after 100 seconds
        utcnow.return_value = T2_DATE
        token_info = self.jwt.get_access_token()
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token, {'key': datafile('public_cert.pem')},
            audience=self.url)
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(token_info.expires_in, T1_EXPIRY - T2)

        # Verify that we vend a new token after _MAX_TOKEN_LIFETIME_SECS
        utcnow.return_value = T3_DATE
        time.return_value = T3
        token_info = self.jwt.get_access_token()
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token, {'key': datafile('public_cert.pem')},
            audience=self.url)
        expires_in = token_info.expires_in
        self.assertEqual(payload['iat'], T3)
        self.assertEqual(payload['exp'], T3_EXPIRY)
        self.assertEqual(expires_in, T3_EXPIRY - T3)
Beispiel #3
0
 def _check_jwt_failure(self, jwt, expected_error):
     public_key = datafile("publickey.pem")
     certs = {"foo": public_key}
     audience = "https://www.googleapis.com/auth/id?client_id=" "*****@*****.**"
     try:
         crypt.verify_signed_jwt_with_certs(jwt, certs, audience)
         self.fail()
     except crypt.AppIdentityError as e:
         self.assertTrue(expected_error in str(e))
Beispiel #4
0
 def _check_jwt_failure(self, jwt, expected_error):
     public_key = datafile('publickey.pem')
     certs = {'foo': public_key}
     audience = ('https://www.googleapis.com/auth/id?client_id='
                 '*****@*****.**')
     try:
         crypt.verify_signed_jwt_with_certs(jwt, certs, audience)
         self.fail()
     except crypt.AppIdentityError as e:
         self.assertTrue(expected_error in str(e))
Beispiel #5
0
    def test_jwt_no_segments(self):
        exception_caught = None
        try:
            crypt.verify_signed_jwt_with_certs(b'', None)
        except crypt.AppIdentityError as exc:
            exception_caught = exc

        self.assertNotEqual(exception_caught, None)
        self.assertTrue(str(exception_caught).startswith(
            'Wrong number of segments in token'))
Beispiel #6
0
    def _check_jwt_failure(self, jwt, expected_error):
        public_key = datafile('public_cert.pem')
        certs = {'foo': public_key}
        audience = ('https://www.googleapis.com/auth/id?client_id='
                    '*****@*****.**')

        with self.assertRaises(crypt.AppIdentityError) as exc_manager:
            crypt.verify_signed_jwt_with_certs(jwt, certs, audience)

        self.assertTrue(expected_error in str(exc_manager.exception))
    def test_jwt_payload_bad_json(self):
        header = signature = b''
        payload = base64.b64encode(b'{BADJSON')
        jwt = b'.'.join([header, payload, signature])

        exception_caught = None
        try:
            crypt.verify_signed_jwt_with_certs(jwt, None)
        except crypt.AppIdentityError as exc:
            exception_caught = exc

        self.assertNotEqual(exception_caught, None)
        self.assertTrue(str(exception_caught).startswith('Can\'t parse token'))
Beispiel #8
0
    def test_jwt_payload_bad_json(self):
        header = signature = b''
        payload = base64.b64encode(b'{BADJSON')
        jwt = b'.'.join([header, payload, signature])

        exception_caught = None
        try:
            crypt.verify_signed_jwt_with_certs(jwt, None)
        except crypt.AppIdentityError as exc:
            exception_caught = exc

        self.assertNotEqual(exception_caught, None)
        self.assertTrue(str(exception_caught).startswith(
            'Can\'t parse token'))
Beispiel #9
0
    def verify_id_token(id_token,
                        audience,
                        http=None,
                        cert_uri=ID_TOKEN_VERIFICATON_CERTS):
        """Verifies a signed JWT id_token.

    Args:
      id_token: string, A Signed JWT.
      audience: string, The audience 'aud' that the token should be for.
      http: httplib2.Http, instance to use to make the HTTP request. Callers
        should supply an instance that has caching enabled.
      cert_uri: string, URI of the certificates in JSON format to
        verify the JWT against.

    Returns:
      The deserialized JSON in the JWT.

    Raises:
      oauth2client.crypt.AppIdentityError if the JWT fails to verify.
    """
        if http is None:
            http = _cached_http

        resp, content = http.request(cert_uri)

        if resp.status == 200:
            certs = simplejson.loads(content)
            return verify_signed_jwt_with_certs(id_token, certs, audience)
        else:
            raise VerifyJwtTokenError('Status code: %d' % resp.status)
    def test_authorize_success(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        http = http_mock.HttpMockSequence([
            ({'status': http_client.OK}, b''),
            ({'status': http_client.OK}, b''),
        ])

        self.jwt.authorize(http)
        transport.request(http, self.url)

        # Ensure we use the cached token
        utcnow.return_value = T2_DATE
        transport.request(http, self.url)

        # Verify mocks.
        certs = {'key': datafile('public_cert.pem')}
        self.assertEqual(len(http.requests), 2)
        for info in http.requests:
            self.assertEqual(info['method'], 'GET')
            self.assertEqual(info['uri'], self.url)
            self.assertIsNone(info['body'])
            self.assertEqual(len(info['headers']), 1)
            bearer, token = info['headers'][b'Authorization'].split()
            self.assertEqual(bearer, b'Bearer')
            payload = crypt.verify_signed_jwt_with_certs(
                token, certs, audience=self.url)
            self.assertEqual(len(payload), 5)
            self.assertEqual(payload['iss'], self.service_account_email)
            self.assertEqual(payload['sub'], self.service_account_email)
            self.assertEqual(payload['iat'], T1)
            self.assertEqual(payload['exp'], T1_EXPIRY)
            self.assertEqual(payload['aud'], self.url)
Beispiel #11
0
  def verify_id_token(id_token, audience, http=None,
      cert_uri=ID_TOKEN_VERIFICATON_CERTS):
    """Verifies a signed JWT id_token.

    Args:
      id_token: string, A Signed JWT.
      audience: string, The audience 'aud' that the token should be for.
      http: httplib2.Http, instance to use to make the HTTP request. Callers
        should supply an instance that has caching enabled.
      cert_uri: string, URI of the certificates in JSON format to
        verify the JWT against.

    Returns:
      The deserialized JSON in the JWT.

    Raises:
      oauth2client.crypt.AppIdentityError if the JWT fails to verify.
    """
    if http is None:
      http = _cached_http

    resp, content = http.request(cert_uri)

    if resp.status == 200:
      certs = simplejson.loads(content)
      return verify_signed_jwt_with_certs(id_token, certs, audience)
    else:
      raise VerifyJwtTokenError('Status code: %d' % resp.status)
 def test_verify_id_token(self):
   jwt = self._create_signed_jwt()
   public_key = datafile('publickey.pem')
   certs = {'foo': public_key }
   audience = '*****@*****.**'
   contents = crypt.verify_signed_jwt_with_certs(jwt, certs, audience)
   self.assertEqual('billy bob', contents['user'])
   self.assertEqual('data', contents['metadata']['meta'])
 def test_verify_id_token(self):
     jwt = self._create_signed_jwt()
     public_key = datafile("publickey.pem")
     certs = {"foo": public_key}
     audience = "*****@*****.**"
     contents = crypt.verify_signed_jwt_with_certs(jwt, certs, audience)
     self.assertEqual("billy bob", contents["user"])
     self.assertEqual("data", contents["metadata"]["meta"])
 def _check_jwt_failure(self, jwt, expected_error):
     try:
         public_key = datafile('publickey.pem')
         certs = {'foo': public_key}
         audience = 'https://www.googleapis.com/auth/id?client_id=' + \
             '*****@*****.**'
         contents = crypt.verify_signed_jwt_with_certs(jwt, certs, audience)
         self.fail('Should have thrown for %s' % jwt)
     except:
         e = sys.exc_info()[1]
         msg = e.args[0]
         self.assertTrue(expected_error in msg)
    def test_authorize_401(self, utcnow):
        utcnow.return_value = T1_DATE

        http = http_mock.HttpMockSequence([
            ({
                'status': http_client.OK
            }, b''),
            ({
                'status': http_client.UNAUTHORIZED
            }, b''),
            ({
                'status': http_client.OK
            }, b''),
        ])
        self.jwt.authorize(http)
        transport.request(http, self.url)
        token_1 = self.jwt.access_token

        utcnow.return_value = T2_DATE
        response, _ = transport.request(http, self.url)
        self.assertEquals(response.status, http_client.OK)
        token_2 = self.jwt.access_token
        # Check the 401 forced a new token
        self.assertNotEqual(token_1, token_2)

        # Verify mocks.
        certs = {'key': datafile('public_cert.pem')}
        self.assertEqual(len(http.requests), 3)
        issued_at_vals = (T1, T1, T2)
        exp_vals = (T1_EXPIRY, T1_EXPIRY, T2_EXPIRY)
        for info, issued_at, exp_val in zip(http.requests, issued_at_vals,
                                            exp_vals):
            self.assertEqual(info['uri'], self.url)
            self.assertEqual(info['method'], 'GET')
            self.assertIsNone(info['body'])
            self.assertEqual(len(info['headers']), 1)
            bearer, token = info['headers'][b'Authorization'].split()
            self.assertEqual(bearer, b'Bearer')
            # To parse the token, skip the time check, since this
            # test intentionally has stale tokens.
            with mock.patch('oauth2client.crypt._verify_time_range',
                            return_value=True):
                payload = crypt.verify_signed_jwt_with_certs(token,
                                                             certs,
                                                             audience=self.url)
            self.assertEqual(len(payload), 5)
            self.assertEqual(payload['iss'], self.service_account_email)
            self.assertEqual(payload['sub'], self.service_account_email)
            self.assertEqual(payload['iat'], issued_at)
            self.assertEqual(payload['exp'], exp_val)
            self.assertEqual(payload['aud'], self.url)
 def mock_request(uri, method='GET', body=None, headers=None,
                  redirections=0, connection_type=None):
     self.assertEqual(uri, self.url)
     bearer, token = headers[b'Authorization'].split()
     payload = crypt.verify_signed_jwt_with_certs(
         token,
         {'key': datafile('public_cert.pem')},
         audience=self.url)
     self.assertEqual(payload['iss'], self.service_account_email)
     self.assertEqual(payload['sub'], self.service_account_email)
     self.assertEqual(payload['iat'], T1)
     self.assertEqual(payload['exp'], T1_EXPIRY)
     self.assertEqual(uri, self.url)
     self.assertEqual(bearer, b'Bearer')
     return (httplib2.Response({'status': '200'}), b'')
Beispiel #17
0
 def mock_request(uri, method='GET', body=None, headers=None,
                  redirections=0, connection_type=None):
     self.assertEqual(uri, self.url)
     bearer, token = headers[b'Authorization'].split()
     payload = crypt.verify_signed_jwt_with_certs(
         token,
         {'key': datafile('public_cert.pem')},
         audience=self.url)
     self.assertEqual(payload['iss'], self.service_account_email)
     self.assertEqual(payload['sub'], self.service_account_email)
     self.assertEqual(payload['iat'], T1)
     self.assertEqual(payload['exp'], T1_EXPIRY)
     self.assertEqual(uri, self.url)
     self.assertEqual(bearer, b'Bearer')
     return (httplib2.Response({'status': '200'}), b'')
Beispiel #18
0
def verify_google_id_token(token):
    """Verify the id token against the Google public keys. Note that this
    function does *not* validate the hosted domain (hd) claim. It *does* verify
    the issuer (iss) claim.

    If verification fails, an oauth2client.crypt.AppIdentityError is raised.
    """
    certs = current_app.config.get('GOOGLE_OAUTH2_CERTS', _get_default_certs())
    client_ids = current_app.config.get('GOOGLE_OAUTH2_ALLOWED_CLIENT_IDS', [])
    idinfo = crypt.verify_signed_jwt_with_certs(token, certs, None)
    if idinfo.get('aud') not in client_ids:
        raise crypt.AppIdentityError('invalid aud: %s' % idinfo.get('aud'))
    if idinfo.get('iss') not in _GOOGLE_ISSUERS:
        raise crypt.AppIdentityError('invalid issuer: %s' % idinfo.get('iss'))
    return idinfo
Beispiel #19
0
def get_token():
    """ Creates an authentication token for valid service credentials.

    Returns:
        A JSON string containing a bearer token.
    """
    config = current_app.config
    try:
        jwt = request.form['assertion']
    except KeyError:
        return error('JWT assertion not defined.', HTTP_BAD_REQUEST)

    valid_users = config['USERS']

    public_keys = {}
    for user in valid_users:
        with open(valid_users[user]['certificate']) as certificate:
            public_keys[user] = certificate.read()

    try:
        payload = verify_signed_jwt_with_certs(jwt,
                                               public_keys,
                                               audience=request.url)
    except AppIdentityError:
        return error('Unable to verify assertion.', HTTP_UNAUTHORIZED)

    try:
        user = payload['iss']
    except KeyError:
        return error('User not defined in JWT assertion.', HTTP_BAD_REQUEST)

    if user not in valid_users:
        return error('{} not configured.'.format(user), HTTP_UNAUTHORIZED)

    token = ''.join(
        random.choice(string.ascii_letters + string.digits + '._-')
        for _ in range(config['ACCESS_TOKEN_LENGTH']))
    current_app.logger.debug('new token: {}'.format(token))

    expiration = datetime.timedelta(seconds=config['TOKEN_EXPIRATION'])
    set_token(token, user, expiration=datetime.datetime.now() + expiration)

    response = {
        'access_token': token,
        'token_type': 'Bearer',
        'expires_in': config['TOKEN_EXPIRATION']
    }
    return Response(json.dumps(response), mimetype='application/json')
  def VerifyGitkitToken(self, jwt):
    """Verifies a Gitkit token string.

    Args:
      jwt: string, the token to be checked

    Returns:
      GitkitUser, if the token is valid. None otherwise.
    """
    certs = self.rpc_helper.GetPublicCert()
    crypt.MAX_TOKEN_LIFETIME_SECS = 30 * 86400  # 30 days
    try:
      parsed = crypt.verify_signed_jwt_with_certs(jwt, certs, self.client_id)
      return GitkitUser.FromToken(parsed)
    except crypt.AppIdentityError:
      return None
    def VerifyGitkitToken(self, jwt):
        """Verifies a Gitkit token string.

    Args:
      jwt: string, the token to be checked

    Returns:
      GitkitUser, if the token is valid. None otherwise.
    """
        certs = self.rpc_helper.GetPublicCert()
        crypt.MAX_TOKEN_LIFETIME_SECS = 30 * 86400  # 30 days
        try:
            parsed = crypt.verify_signed_jwt_with_certs(
                jwt, certs, self.client_id)
            return GitkitUser.FromToken(parsed)
        except crypt.AppIdentityError:
            return None
Beispiel #22
0
    def test_get_access_token_additional_claims(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        token_info = self.jwt.get_access_token(additional_claims={
            'aud': 'https://test2.url.com',
            'sub': '*****@*****.**'
        })
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token, {'key': datafile('public_cert.pem')},
            audience='https://test2.url.com')
        expires_in = token_info.expires_in
        self.assertEqual(payload['iss'], self.service_account_email)
        self.assertEqual(payload['sub'], '*****@*****.**')
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(expires_in, T1_EXPIRY - T1)
    def test_get_access_token_additional_claims(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        token_info = self.jwt.get_access_token(additional_claims=
                                               {'aud': 'https://test2.url.com',
                                                'sub': '*****@*****.**'
                                               })
        payload = crypt.verify_signed_jwt_with_certs(
            token_info.access_token,
            {'key' : datafile('public_cert.pem')}, 
            audience='https://test2.url.com')
        expires_in = token_info.expires_in
        self.assertEqual(payload['iss'], self.service_account_email)
        self.assertEqual(payload['sub'], '*****@*****.**')
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(expires_in, T1_EXPIRY - T1)
    def test_authorize_401(self, utcnow):
        utcnow.return_value = T1_DATE

        http = http_mock.HttpMockSequence([
            ({'status': http_client.OK}, b''),
            ({'status': http_client.UNAUTHORIZED}, b''),
            ({'status': http_client.OK}, b''),
        ])
        self.jwt.authorize(http)
        transport.request(http, self.url)
        token_1 = self.jwt.access_token

        utcnow.return_value = T2_DATE
        response, _ = transport.request(http, self.url)
        self.assertEquals(response.status, http_client.OK)
        token_2 = self.jwt.access_token
        # Check the 401 forced a new token
        self.assertNotEqual(token_1, token_2)

        # Verify mocks.
        certs = {'key': datafile('public_cert.pem')}
        self.assertEqual(len(http.requests), 3)
        issued_at_vals = (T1, T1, T2)
        exp_vals = (T1_EXPIRY, T1_EXPIRY, T2_EXPIRY)
        for info, issued_at, exp_val in zip(http.requests, issued_at_vals,
                                            exp_vals):
            self.assertEqual(info['uri'], self.url)
            self.assertEqual(info['method'], 'GET')
            self.assertIsNone(info['body'])
            self.assertEqual(len(info['headers']), 1)
            bearer, token = info['headers'][b'Authorization'].split()
            self.assertEqual(bearer, b'Bearer')
            # To parse the token, skip the time check, since this
            # test intentionally has stale tokens.
            with mock.patch('oauth2client.crypt._verify_time_range',
                            return_value=True):
                payload = crypt.verify_signed_jwt_with_certs(
                    token, certs, audience=self.url)
            self.assertEqual(len(payload), 5)
            self.assertEqual(payload['iss'], self.service_account_email)
            self.assertEqual(payload['sub'], self.service_account_email)
            self.assertEqual(payload['iat'], issued_at)
            self.assertEqual(payload['exp'], exp_val)
            self.assertEqual(payload['aud'], self.url)
Beispiel #25
0
def verify_id_token(id_token, cert_uri, audience=None, kid=None, http=None):
    """Verifies the provided ID token.

    Checks for token integrity by verifying its signature against
    a set of public key certificates. Certificates are downloaded
    from cert_uri, and cached according to the HTTP cache control
    requirements. If provided, the audience and kid fields of the
    ID token are also validated.

    Args:
      id_token: JWT ID token to be validated.
      cert_uri: A URI string pointing to public key certificates.
      audience: Audience string that should be present in the token.
      kid: JWT key ID header to locate the public key certificate.
      http: An httplib2 HTTP client instance.

    Returns:
      dict: A dictionary of claims extracted from the ID token.

    Raises:
      ValueError: Certificate URI is None or empty.
      AppIdentityError: Token integrity check failed.
      VerifyJwtTokenError: Failed to load public keys or invalid kid header.
    """
    if not cert_uri:
        raise ValueError('Certificate URI is required')
    if not http:
        http = _cached_http
    resp, content = http.request(cert_uri)
    if resp.status != 200:
        raise client.VerifyJwtTokenError(
            ('Failed to load public key certificates from URL "{0}". Received '
             'HTTP status code {1}.').format(cert_uri, resp.status))
    str_content = content.decode('utf-8') if isinstance(
        content, six.binary_type) else content
    certs = json.loads(str_content)
    if kid and kid not in certs:
        raise client.VerifyJwtTokenError(
            'Firebase ID token has "kid" claim which does'
            ' not correspond to a known public key. Most'
            ' likely the ID token is expired, so get a'
            ' fresh token from your client app and try again.')
    return crypt.verify_signed_jwt_with_certs(id_token, certs, audience)
    def test_authorize_no_aud(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        jwt = service_account._JWTAccessCredentials(
            self.service_account_email,
            self.signer,
            private_key_id=self.private_key_id,
            client_id=self.client_id)

        http = http_mock.HttpMockSequence([
            ({
                'status': http_client.OK
            }, b''),
        ])

        jwt.authorize(http)
        transport.request(http, self.url)

        # Ensure we do not cache the token
        self.assertIsNone(jwt.access_token)

        # Verify mocks.
        self.assertEqual(len(http.requests), 1)
        info = http.requests[0]
        self.assertEqual(info['method'], 'GET')
        self.assertEqual(info['uri'], self.url)
        self.assertIsNone(info['body'])
        self.assertEqual(len(info['headers']), 1)
        bearer, token = info['headers'][b'Authorization'].split()
        self.assertEqual(bearer, b'Bearer')
        certs = {'key': datafile('public_cert.pem')}
        payload = crypt.verify_signed_jwt_with_certs(token,
                                                     certs,
                                                     audience=self.url)
        self.assertEqual(len(payload), 5)
        self.assertEqual(payload['iss'], self.service_account_email)
        self.assertEqual(payload['sub'], self.service_account_email)
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(payload['aud'], self.url)
  def VerifyGitkitToken(self, jwt):
    """Verifies a Gitkit token string.

    Args:
      jwt: string, the token to be checked

    Returns:
      GitkitUser, if the token is valid. None otherwise.
    """
    certs = self.rpc_helper.GetPublicCert()
    crypt.MAX_TOKEN_LIFETIME_SECS = 30 * 86400  # 30 days
    parsed = None
    for aud in filter(lambda x: x is not None, [self.project_id, self.client_id]):
      try:
        parsed = crypt.verify_signed_jwt_with_certs(jwt, certs, aud)
      except crypt.AppIdentityError as e:
        if "Wrong recipient" not in e.message:
          return None
      if parsed:
        return GitkitUser.FromToken(parsed)
    return None # Gitkit token audience doesn't match projectId or clientId in server configuration
  def VerifyGitkitToken(self, jwt):
    """Verifies a Gitkit token string.

    Args:
      jwt: string, the token to be checked

    Returns:
      GitkitUser, if the token is valid. None otherwise.
    """
    certs = self.rpc_helper.GetPublicCert()
    crypt.MAX_TOKEN_LIFETIME_SECS = 30 * 86400  # 30 days
    parsed = None
    for aud in filter(lambda x: x is not None, [self.project_id, self.client_id]):
      try:
        parsed = crypt.verify_signed_jwt_with_certs(jwt, certs, aud)
      except crypt.AppIdentityError as e:
        if "Wrong recipient" not in e.message:
          return None
      if parsed:
        return GitkitUser.FromToken(parsed)
    return None # Gitkit token audience doesn't match projectId or clientId in server configuration
    def test_authorize_success(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        http = http_mock.HttpMockSequence([
            ({
                'status': http_client.OK
            }, b''),
            ({
                'status': http_client.OK
            }, b''),
        ])

        self.jwt.authorize(http)
        transport.request(http, self.url)

        # Ensure we use the cached token
        utcnow.return_value = T2_DATE
        transport.request(http, self.url)

        # Verify mocks.
        certs = {'key': datafile('public_cert.pem')}
        self.assertEqual(len(http.requests), 2)
        for info in http.requests:
            self.assertEqual(info['method'], 'GET')
            self.assertEqual(info['uri'], self.url)
            self.assertIsNone(info['body'])
            self.assertEqual(len(info['headers']), 1)
            bearer, token = info['headers'][b'Authorization'].split()
            self.assertEqual(bearer, b'Bearer')
            payload = crypt.verify_signed_jwt_with_certs(token,
                                                         certs,
                                                         audience=self.url)
            self.assertEqual(len(payload), 5)
            self.assertEqual(payload['iss'], self.service_account_email)
            self.assertEqual(payload['sub'], self.service_account_email)
            self.assertEqual(payload['iat'], T1)
            self.assertEqual(payload['exp'], T1_EXPIRY)
            self.assertEqual(payload['aud'], self.url)
    def test_authorize_no_aud(self, time, utcnow):
        utcnow.return_value = T1_DATE
        time.return_value = T1

        jwt = service_account._JWTAccessCredentials(
            self.service_account_email, self.signer,
            private_key_id=self.private_key_id, client_id=self.client_id)

        http = http_mock.HttpMockSequence([
            ({'status': http_client.OK}, b''),
        ])

        jwt.authorize(http)
        transport.request(http, self.url)

        # Ensure we do not cache the token
        self.assertIsNone(jwt.access_token)

        # Verify mocks.
        self.assertEqual(len(http.requests), 1)
        info = http.requests[0]
        self.assertEqual(info['method'], 'GET')
        self.assertEqual(info['uri'], self.url)
        self.assertIsNone(info['body'])
        self.assertEqual(len(info['headers']), 1)
        bearer, token = info['headers'][b'Authorization'].split()
        self.assertEqual(bearer, b'Bearer')
        certs = {'key': datafile('public_cert.pem')}
        payload = crypt.verify_signed_jwt_with_certs(
            token, certs, audience=self.url)
        self.assertEqual(len(payload), 5)
        self.assertEqual(payload['iss'], self.service_account_email)
        self.assertEqual(payload['sub'], self.service_account_email)
        self.assertEqual(payload['iat'], T1)
        self.assertEqual(payload['exp'], T1_EXPIRY)
        self.assertEqual(payload['aud'], self.url)
Beispiel #31
0
    def test_success(self, verify_sig, verify_time, check_aud):
        certs = mock.MagicMock()
        cert_values = object()
        certs.values = mock.MagicMock(name='values',
                                      return_value=cert_values)
        audience = object()

        header = b'header'
        signature_bytes = b'signature'
        signature = base64.b64encode(signature_bytes)
        payload_dict = {'a': 'b'}
        payload = base64.b64encode(b'{"a": "b"}')
        jwt = b'.'.join([header, payload, signature])

        result = crypt.verify_signed_jwt_with_certs(
            jwt, certs, audience=audience)
        self.assertEqual(result, payload_dict)

        message_to_sign = header + b'.' + payload
        verify_sig.assert_called_once_with(
            message_to_sign, signature_bytes, cert_values)
        verify_time.assert_called_once_with(payload_dict)
        check_aud.assert_called_once_with(payload_dict, audience)
        certs.values.assert_called_once_with()