def make_signed_jwt(signer, payload, key_id=None): """Make a signed JWT. See http://self-issued.info/docs/draft-jones-json-web-token.html. Args: signer: crypt.Signer, Cryptographic signer. payload: dict, Dictionary of data to convert to JSON and then sign. key_id: string, (Optional) Key ID header. Returns: string, The JWT for the payload. """ header = {'typ': 'JWT', 'alg': 'RS256'} if key_id is not None: header['kid'] = key_id segments = [ _helpers._urlsafe_b64encode(_helpers._json_encode(header)), _helpers._urlsafe_b64encode(_helpers._json_encode(payload)), ] signing_input = b'.'.join(segments) signature = signer.sign(signing_input) segments.append(_helpers._urlsafe_b64encode(signature)) logger.debug(str(segments)) return b'.'.join(segments)
def _generate_assertion(self): """Generate the assertion that will be used in the request.""" header = { 'alg': 'RS256', 'typ': 'JWT', 'kid': self._private_key_id } now = int(time.time()) payload = { 'aud': self._token_uri, 'scope': self._scopes, 'iat': now, 'exp': now + _ServiceAccountCredentials.MAX_TOKEN_LIFETIME_SECS, 'iss': self._service_account_email } payload.update(self._kwargs) first_segment = _urlsafe_b64encode(_json_encode(header)) second_segment = _urlsafe_b64encode(_json_encode(payload)) assertion_input = first_segment + b'.' + second_segment # Sign the assertion. rsa_bytes = rsa.pkcs1.sign(assertion_input, self._private_key, 'SHA-256') signature = base64.urlsafe_b64encode(rsa_bytes).rstrip(b'=') return assertion_input + b'.' + signature
def test_verify_id_token_bad_tokens(self): private_key = datafile('privatekey.' + self.format_) # Wrong number of segments self._check_jwt_failure('foo', 'Wrong number of segments') # Not json self._check_jwt_failure('foo.bar.baz', 'Can\'t parse token') # Bad signature jwt = b'.'.join( [b'foo', _helpers._urlsafe_b64encode('{"a":"b"}'), b'baz']) self._check_jwt_failure(jwt, 'Invalid token signature') # No expiration signer = self.signer.from_string(private_key) audience = ('https:#www.googleapis.com/auth/id?client_id=' '*****@*****.**') jwt = crypt.make_signed_jwt(signer, { 'aud': audience, 'iat': time.time(), }) self._check_jwt_failure(jwt, 'No exp field in token') # No issued at jwt = crypt.make_signed_jwt(signer, { 'aud': 'audience', 'exp': time.time() + 400, }) self._check_jwt_failure(jwt, 'No iat field in token') # Too early jwt = crypt.make_signed_jwt( signer, { 'aud': 'audience', 'iat': time.time() + 301, 'exp': time.time() + 400, }) self._check_jwt_failure(jwt, 'Token used too early') # Too late jwt = crypt.make_signed_jwt( signer, { 'aud': 'audience', 'iat': time.time() - 500, 'exp': time.time() - 301, }) self._check_jwt_failure(jwt, 'Token used too late') # Wrong target jwt = crypt.make_signed_jwt(signer, { 'aud': 'somebody else', 'iat': time.time(), 'exp': time.time() + 300, }) self._check_jwt_failure(jwt, 'Wrong recipient')
def test_verify_id_token_bad_tokens(self): private_key = datafile('privatekey.' + self.format_) # Wrong number of segments self._check_jwt_failure('foo', 'Wrong number of segments') # Not json self._check_jwt_failure('foo.bar.baz', 'Can\'t parse token') # Bad signature jwt = b'.'.join([b'foo', _helpers._urlsafe_b64encode('{"a":"b"}'), b'baz']) self._check_jwt_failure(jwt, 'Invalid token signature') # No expiration signer = self.signer.from_string(private_key) audience = ('https:#www.googleapis.com/auth/id?client_id=' '*****@*****.**') jwt = crypt.make_signed_jwt(signer, { 'aud': audience, 'iat': time.time(), }) self._check_jwt_failure(jwt, 'No exp field in token') # No issued at jwt = crypt.make_signed_jwt(signer, { 'aud': 'audience', 'exp': time.time() + 400, }) self._check_jwt_failure(jwt, 'No iat field in token') # Too early jwt = crypt.make_signed_jwt(signer, { 'aud': 'audience', 'iat': time.time() + 301, 'exp': time.time() + 400, }) self._check_jwt_failure(jwt, 'Token used too early') # Too late jwt = crypt.make_signed_jwt(signer, { 'aud': 'audience', 'iat': time.time() - 500, 'exp': time.time() - 301, }) self._check_jwt_failure(jwt, 'Token used too late') # Wrong target jwt = crypt.make_signed_jwt(signer, { 'aud': 'somebody else', 'iat': time.time(), 'exp': time.time() + 300, }) self._check_jwt_failure(jwt, 'Wrong recipient')
def getWrongAccessToken(): """This view simulates a Google sign-in API response to a request for a redirect URI. Returns a JSON response. In this case, we're sending a response missing it's access_token parameter in order to test that scenario. """ id_token = '{"sub": "110169484474386276334", "email": "*****@*****.**"}' id_token_encoded = _urlsafe_b64encode(id_token) # no access token this time token_response = {'id_token': 'app.' + id_token_encoded + '.catalog'} return jsonify(token_response)
def getWrongAccessToken(): """This view simulates a Google sign-in API response to a request for a redirect URI. Returns a JSON response. In this case, we're sending a response missing it's access_token parameter in order to test that scenario. """ id_token = '{"sub": "110169484474386276334", "email": "*****@*****.**"}' id_token_encoded = _urlsafe_b64encode(id_token) # no access token this time token_response = { 'id_token': 'app.' + id_token_encoded + '.catalog' } return jsonify(token_response)
def getAccessToken(): """This view simulates a Google sign-in API response to a request for a redirect URI. Returns a JSON response. """ id_token = '{"sub": "110169484474386276334", "email": "*****@*****.**"}' # Google Base64-encodes the id_token, so we must also for the # test to work id_token_encoded = _urlsafe_b64encode(id_token) # note the fake access_token; in this case, the token is not # validated so it can be whatever we want # the id_token sent to Google must be a string delimited by # '.'; Google looks for three segments (using split()) and takes # the middle one, hence the configuration shown here token_response = { 'access_token': 'splunge', 'id_token': 'app.' + id_token_encoded + '.catalog' } return jsonify(token_response)
def test_valid_input_unicode(self): test_string = u'deadbeef' result = _urlsafe_b64encode(test_string) self.assertEqual(result, self.DEADBEEF_ENCODED)
def test_valid_input_unicode(self): test_string = u'deadbeef' result = _helpers._urlsafe_b64encode(test_string) self.assertEqual(result, self.DEADBEEF_ENCODED)
def test_valid_input_bytes(self): test_string = b'deadbeef' result = _helpers._urlsafe_b64encode(test_string) self.assertEqual(result, self.DEADBEEF_ENCODED)
def test_valid_input_unicode(self): test_string = u'deadbeef' result = _urlsafe_b64encode(test_string) self.assertEqual(result, u'ZGVhZGJlZWY')
def test_valid_input_bytes(self): test_string = b'deadbeef' result = _urlsafe_b64encode(test_string) self.assertEqual(result, self.DEADBEEF_ENCODED)
def get_google_events(calendar_events): g = conf['google'] with open(g['json_file'], 'r') as file_obj: client_credentials = json.load(file_obj) private_key_pkcs8_pem = client_credentials['private_key'] signer = _pure_python_crypt.RsaSigner.from_string(private_key_pkcs8_pem) header = {'typ': 'JWT', 'alg': 'RS256'} now = int(time.time()) payload = { 'aud': 'https://www.googleapis.com/oauth2/v4/token', 'scope': g['scopes'], 'iat': now, 'exp': now + 3600, # 1 hour in seconds 'iss': g['email_address'] } segments = [ _helpers._urlsafe_b64encode(_helpers._json_encode(header)), _helpers._urlsafe_b64encode(_helpers._json_encode(payload)), ] signing_input = b'.'.join(segments) signature = signer.sign(signing_input) segments.append(_helpers._urlsafe_b64encode(signature)) claim = b'.'.join(segments) post_data = { 'grant_type':'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion':claim } req = requests.post('https://www.googleapis.com/oauth2/v4/token', post_data) resp = req.json() access_token = resp['access_token'] auth_header = { 'Authorization':'Bearer ' + access_token } calendar_url = 'https://www.googleapis.com/calendar/v3/calendars/[email protected]/events' hel_time = datetime.datetime.now(tz) start_time = hel_time.strftime('%Y-%m-%dT00:00:00+02') get_data = { 'maxResults':100, 'orderBy':'startTime', 'singleEvents':'true', 'timeMin':start_time } req = requests.get(calendar_url, params = get_data, headers = auth_header) #req = requests.get(calendar_list_url, headers = auth_header) resp = req.json() for item in resp['items']: start_time_item = item['start'] start_time = parse_google_event_datetime(item['start']) end_time = parse_google_event_datetime(item['end']) event = { 'summary': item.get('summary', ''), 'location': item.get('location', ''), 'start_time': start_time, 'end_time': end_time } add_event(calendar_events, event)