def _test_with_lock(self, lock_timeout, update_fsa_fxn=None, api_json=None): expected_json = 'fake service account json' if not api_json: api_json = expected_json caller_uid = self._random_subject_id() real_user_id = self._random_subject_id() ftvm = FenceTokenVendingMachine(self._mock_fence_api(api_json), self._mock_sam_api(real_user_id, "*****@*****.**"), self._mock_oauth_adapter("fake_token"), provider_name) TokenStore.save(real_user_id, "fake_refresh_token", datetime.datetime.now(), "*****@*****.**", provider_name) fsa_key = ftvm._fence_service_account_key(real_user_id) stored_fsa = FenceServiceAccount(key_json="expired json", expires_at=datetime.datetime.now() - datetime.timedelta(days=5), update_lock_timeout=lock_timeout, key=fsa_key) stored_fsa.put() self.assertIsNone(memcache.get(namespace=provider_name, key=caller_uid)) if update_fsa_fxn: threading.Thread(target=update_fsa_fxn, args=(fsa_key, expected_json)).start() service_account_json = ftvm.get_service_account_key_json( UserInfo(caller_uid, "*****@*****.**", "fake_token_too", 10)) self.assertEqual(expected_json, service_account_json) self.assertIsNotNone(memcache.get(namespace=provider_name, key=caller_uid)) stored_fsa = fsa_key.get() self.assertIsNotNone(stored_fsa) self.assertIsNone(stored_fsa.update_lock_timeout) self.assertEqual(expected_json, stored_fsa.key_json) self.assertGreater(stored_fsa.expires_at, datetime.datetime.now())
def middleware(request): # process request token = request.META.get('HTTP_ACCESS_TOKEN') token_session = TokenStore(token) # 自动为request添加token_session request.token_session = token_session response = get_response(request) # process response try: accessed = token_session.accessed modified = token_session.modified empty = token_session.is_empty() except AttributeError: pass else: if accessed: if modified and not empty: if response.status_code != 500: try: request.token_session.save() except UpdateError: raise SuspiciousOperation( "The request's token session was deleted before the " "request completed. The user may have logged " "out in a concurrent request, for example.") return response
def test_no_service_account(self): expected_json = 'fake service account json' caller_uid = self._random_subject_id() real_user_id = self._random_subject_id() ftvm = FenceTokenVendingMachine(self._mock_fence_api(expected_json), self._mock_sam_api(real_user_id, "*****@*****.**"), self._mock_oauth_adapter("fake_token"), provider_name) TokenStore.save(real_user_id, "fake_refresh_token", datetime.datetime.now(), "*****@*****.**", provider_name) self.assertIsNone(memcache.get(namespace=provider_name, key=caller_uid)) fsa_key = ftvm._fence_service_account_key(real_user_id) self.assertIsNone(fsa_key.get()) service_account_json = ftvm.get_service_account_key_json( UserInfo(caller_uid, "*****@*****.**", "fake_token_too", 10)) self.assertEqual(expected_json, service_account_json) self.assertIsNotNone(memcache.get(namespace=provider_name, key=caller_uid)) stored_fsa = fsa_key.get() self.assertIsNotNone(stored_fsa) self.assertIsNone(stored_fsa.update_lock_timeout) self.assertEqual(expected_json, stored_fsa.key_json) self.assertGreater(stored_fsa.expires_at, datetime.datetime.now())
def test_no_service_account(self): expected_json = 'fake service account json' caller_uid = self._random_subject_id() real_user_id = self._random_subject_id() ftvm = FenceTokenVendingMachine( self._mock_fence_api(expected_json), self._mock_sam_api(real_user_id, "*****@*****.**"), self._mock_oauth_adapter("fake_token"), provider_name) TokenStore.save(real_user_id, "fake_refresh_token", datetime.datetime.now(), "*****@*****.**", provider_name) self.assertIsNone(memcache.get(namespace=provider_name, key=caller_uid)) fsa_key = ftvm._fence_service_account_key(real_user_id) self.assertIsNone(fsa_key.get()) service_account_json = ftvm.get_service_account_key_json( UserInfo(caller_uid, "*****@*****.**", "fake_token_too", 10)) self.assertEqual(expected_json, service_account_json) self.assertIsNotNone( memcache.get(namespace=provider_name, key=caller_uid)) stored_fsa = fsa_key.get() self.assertIsNotNone(stored_fsa) self.assertIsNone(stored_fsa.update_lock_timeout) self.assertEqual(expected_json, stored_fsa.key_json) self.assertGreater(stored_fsa.expires_at, datetime.datetime.now())
def get(self): """GET Requests""" listing = self.request.get("listing") self.response.out.write("hello") t = TokenStore() t.listing = listing t.put()
def test_lookup(self): TokenStore.save(self.user_id, self.token_str, self.issued_at, self.username, provider_name) persisted_token = TokenStore.lookup(self.user_id, provider_name) self.assertEqual(self.token_str, persisted_token.token) self.assertEqual(self.issued_at, persisted_token.issued_at) self.assertEqual(self.username, persisted_token.username)
def test_active_service_account_in_ds(self): expected_json = 'fake service account json' caller_uid = self._random_subject_id() real_user_id = self._random_subject_id() ftvm = FenceTokenVendingMachine( None, self._mock_sam_api(real_user_id, "*****@*****.**"), self._mock_oauth_adapter("fake_token"), provider_name) TokenStore.save(real_user_id, "fake_refresh_token", datetime.datetime.now(), "*****@*****.**", provider_name) fsa_key = ftvm._fence_service_account_key(real_user_id) stored_fsa = FenceServiceAccount(key_json=expected_json, expires_at=datetime.datetime.now() + datetime.timedelta(days=5), update_lock_timeout=None, key=fsa_key) stored_fsa.put() self.assertIsNone(memcache.get(namespace=provider_name, key=caller_uid)) service_account_json = ftvm.get_service_account_key_json( UserInfo(caller_uid, "*****@*****.**", "fake_token_too", 10)) self.assertEqual(expected_json, service_account_json) self.assertIsNotNone( memcache.get(namespace=provider_name, key=caller_uid))
def test_link_info_exists(self): token = str(uuid.uuid4()) TokenStore.save(user_id=self.user_id, refresh_token_str=token, issued_at=datetime.fromtimestamp(self.issued_at_epoch), username=self.name, provider_name=provider_name) link_info = self.bond.get_link_info(UserInfo(str(uuid.uuid4()), "", "", 30)) self.assertEqual(token, link_info.token)
def test_generate_access_token(self): token = str(uuid.uuid4()) TokenStore.save(user_id=self.user_id, refresh_token_str=token, issued_at=datetime.fromtimestamp(self.issued_at_epoch), username=self.name, provider_name=provider_name) access_token, expires_at = self.bond.generate_access_token(UserInfo(str(uuid.uuid4()), "", "", 30)) self.assertEqual(self.fake_access_token, access_token) self.assertEqual(datetime.fromtimestamp(self.expires_at_epoch), expires_at)
def unlink_account(self, user_info): """ Revokes user's refresh token and deletes the linkage from the system :param user_info: :return: """ user_id = self.sam_api.user_info(user_info.token)[SamKeys.USER_ID_KEY] refresh_token = TokenStore.lookup(user_id, self.provider_name) if refresh_token: self.fence_tvm.remove_service_account(user_id) self.oauth_adapter.revoke_refresh_token(refresh_token.token) TokenStore.delete(user_id, self.provider_name)
def test_revoke_link_exists(self): token = str(uuid.uuid4()) TokenStore.save(self.user_id, token, datetime.now(), self.name, provider_name) user_info = UserInfo(str(uuid.uuid4()), "", "", 30) self.bond.fence_tvm.get_service_account_key_json(user_info) self.assertIsNotNone(self.bond.fence_tvm._fence_service_account_key(self.user_id).get()) self.bond.unlink_account(user_info) self.assertIsNone(self.bond.fence_tvm._fence_service_account_key(self.user_id).get()) self.assertIsNone(TokenStore.lookup(self.user_id, provider_name)) self.bond.oauth_adapter.revoke_refresh_token.assert_called_once() self.bond.fence_api.delete_credentials_google.assert_called_once()
class Tokenizer: def __init__(self, jack): self.text = jack.strip() self.store = TokenStore() def tokens(self): while self.has_more(): self.store.push(self.next_word()) return self.store def has_more(self): return self.text != '' def next_word(self): first = self.first_letter() if first in SYMBOLS: return self.trimmed_symbol() elif first == '"': return self.trimmed_string() else: return self.trimmed_word() def first_letter(self): self.text = self.text.lstrip() return self.text[0] def trimmed_symbol(self): return self.trim_and_return(1) def trimmed_string(self): close_quote = self.text.find('"', 1) return self.trim_and_return(close_quote+1) def trimmed_word(self): idx = self.next_terminal_idx() return self.trim_and_return(idx) def next_terminal_idx(self): idx = 0 while not (self.text[idx] in SYMBOLS or self.text[idx].isspace()): idx += 1 return idx def trim_and_return(self, count): trimmed = self.text[:count] self.text = self.text[count:] return trimmed
def _get_oauth_access_token(self, user_id): refresh_token = TokenStore.lookup(user_id, self.provider_name) if refresh_token is None: raise endpoints.BadRequestException("Fence account not linked") access_token = self.fence_oauth_adapter.refresh_access_token( refresh_token.token).get(FenceKeys.ACCESS_TOKEN_KEY) return access_token
def get_link_info(self, user_info): """ Get information about a account link :param user_info: Information of the user who issued the request to Bond (not necessarily the same as the username for whom the refresh token was issued by the OAuth provider) :return: refresh_token """ user_id = self.sam_api.user_info(user_info.token)[SamKeys.USER_ID_KEY] return TokenStore.lookup(user_id, self.provider_name)
def test_save(self): self.assertIsNone(self.key.get()) result_key = TokenStore.save(self.user_id, self.token_str, self.issued_at, self.username, provider_name) self.assertEqual(result_key, self.key) saved_token = self.key.get() self.assertIsNotNone(saved_token) self.assertEqual(self.token_str, saved_token.token) self.assertEqual(self.issued_at, saved_token.issued_at) self.assertEqual(self.username, saved_token.username)
def _test_with_lock(self, lock_timeout, update_fsa_fxn=None, api_json=None): expected_json = 'fake service account json' if not api_json: api_json = expected_json caller_uid = self._random_subject_id() real_user_id = self._random_subject_id() ftvm = FenceTokenVendingMachine( self._mock_fence_api(api_json), self._mock_sam_api(real_user_id, "*****@*****.**"), self._mock_oauth_adapter("fake_token"), provider_name) TokenStore.save(real_user_id, "fake_refresh_token", datetime.datetime.now(), "*****@*****.**", provider_name) fsa_key = ftvm._fence_service_account_key(real_user_id) stored_fsa = FenceServiceAccount(key_json="expired json", expires_at=datetime.datetime.now() - datetime.timedelta(days=5), update_lock_timeout=lock_timeout, key=fsa_key) stored_fsa.put() self.assertIsNone(memcache.get(namespace=provider_name, key=caller_uid)) if update_fsa_fxn: threading.Thread(target=update_fsa_fxn, args=(fsa_key, expected_json)).start() service_account_json = ftvm.get_service_account_key_json( UserInfo(caller_uid, "*****@*****.**", "fake_token_too", 10)) self.assertEqual(expected_json, service_account_json) self.assertIsNotNone( memcache.get(namespace=provider_name, key=caller_uid)) stored_fsa = fsa_key.get() self.assertIsNotNone(stored_fsa) self.assertIsNone(stored_fsa.update_lock_timeout) self.assertEqual(expected_json, stored_fsa.key_json) self.assertGreater(stored_fsa.expires_at, datetime.datetime.now())
def exchange_authz_code(self, authz_code, redirect_uri, user_info): """ Given an authz_code and user information, exchange that code for an OAuth Access Token and Refresh Token. Store the refresh token for later, and return the datetime the token was issued along with the username for whom it was issued to by the OAuth provider. :param authz_code: Authorization code from OAuth provider :param redirect_uri: redirect url that was used when generating the code - will use default if None :param user_info: Information of the user who issued the request to Bond (not necessarily the same as the username for whom the refresh token was issued by the OAuth provider) :return: Two values: datetime when token was issued, username for whom the token was issued """ token_response = self.oauth_adapter.exchange_authz_code(authz_code, redirect_uri) jwt_token = JwtToken(token_response.get(FenceKeys.ID_TOKEN), self.user_name_path_expr) user_id = self.sam_api.user_info(user_info.token)[SamKeys.USER_ID_KEY] if FenceKeys.REFRESH_TOKEN_KEY not in token_response: raise endpoints.BadRequestException("authorization response did not include " + FenceKeys.REFRESH_TOKEN_KEY) TokenStore.save(user_id, token_response.get(FenceKeys.REFRESH_TOKEN_KEY), jwt_token.issued_at, jwt_token.username, self.provider_name) return jwt_token.issued_at, jwt_token.username
def setUp(self): # First, create an instance of the Testbed class. self.testbed = testbed.Testbed() # Then activate the testbed, which prepares the service stubs for use. self.testbed.activate() # Next, declare which service stubs you want to use. self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() self.user_id = "abc123" self.token_str = "aaaaaabbbbbbcccccccddddddd" self.issued_at = datetime.now() self.username = "******" self.key = TokenStore._token_store_key(self.user_id, provider_name)
def test_active_service_account_in_ds(self): expected_json = 'fake service account json' caller_uid = self._random_subject_id() real_user_id = self._random_subject_id() ftvm = FenceTokenVendingMachine(None, self._mock_sam_api(real_user_id, "*****@*****.**"), self._mock_oauth_adapter("fake_token"), provider_name) TokenStore.save(real_user_id, "fake_refresh_token", datetime.datetime.now(), "*****@*****.**", provider_name) fsa_key = ftvm._fence_service_account_key(real_user_id) stored_fsa = FenceServiceAccount(key_json=expected_json, expires_at=datetime.datetime.now() + datetime.timedelta(days=5), update_lock_timeout=None, key=fsa_key) stored_fsa.put() self.assertIsNone(memcache.get(namespace=provider_name, key=caller_uid)) service_account_json = ftvm.get_service_account_key_json( UserInfo(caller_uid, "*****@*****.**", "fake_token_too", 10)) self.assertEqual(expected_json, service_account_json) self.assertIsNotNone(memcache.get(namespace=provider_name, key=caller_uid))
def generate_access_token(self, user_info): """ Given a user, lookup their refresh token and use it to generate a new refresh token from their OAuth provider. If a refresh token cannot be found for the user_id provided, a MissingTokenError will be raised. :param user_info: Information of the user who issued the request to Bond (not necessarily the same as the username for whom the refresh token was issued by the OAuth provider) :return: Two values: An Access Token string, datetime when that token expires """ user_id = self.sam_api.user_info(user_info.token)[SamKeys.USER_ID_KEY] refresh_token = TokenStore.lookup(user_id, self.provider_name) if refresh_token is not None: token_response = self.oauth_adapter.refresh_access_token(refresh_token.token) expires_at = datetime.fromtimestamp(token_response.get(FenceKeys.EXPIRES_AT_KEY)) return token_response.get("access_token"), expires_at else: raise Bond.MissingTokenError("Could not find refresh token for user")
def __init__(self, jack): self.text = jack.strip() self.store = TokenStore()
def _get_oauth_access_token(self, user_id): refresh_token = TokenStore.lookup(user_id, self.provider_name) if refresh_token is None: raise endpoints.BadRequestException("Fence account not linked") access_token = self.fence_oauth_adapter.refresh_access_token(refresh_token.token).get(FenceKeys.ACCESS_TOKEN_KEY) return access_token
class AuthResource(BaseResource): def __init__(self): self.token_store = TokenStore() def on_get(self, req, resp, action): if action == 'logout': # development self._logout(req, resp) def on_post(self, req, resp, type): if type == 'auto': self._autoLogin(req, resp) elif type == 'external': self._externalLogin(req, resp) else: self._internalLogin(req, resp) # PRIVATE METHODS def _autoLogin(self, req, resp): """ Create and login an empty user just after extension has been installed """ timezone = req.get_header('X-Timezone') data = json.loads(req.stream.read()) user_exists = False try: if 'user_id' in data and 'password' in data: # need to relogin user # check the user id and password # in case they match -> relogin # otherwise create new user if UserFactory.check_user(data['user_id'], data['password']): user_exists = True token = self.token_store.new(data['user_id'], timezone) if not user_exists and 'password' in data: user = User({'password': data['password']}) user.save() user.reload() except Exception as error: self.error_response(resp, { 'status': falcon.HTTP_400, 'message': str(error) }) return response_data = {'token': token} if not user_exists: response_data['user_id'] = user['_id'] self.success_response(resp, response_data) def _externalLogin(self, req, resp): """ Perform login from from external resources like vk.com or facebook.com """ data = req.stream.read() data = json.loads(data) timezone = req.get_header('X-Timezone') try: user = UserFactory.get_external(data['type'], data['user']) if user is None: user = UserFactory.create_from_external( data['type'], data['user']) user.save() user.reload() except Exception as error: self.error_response(resp, { 'status': falcon.HTTP_400, 'message': str(error) }) return if user['_id'] is not None: token = self.token_store.new(user['_id'], timezone) self.success_response(resp, {'token': token}) else: self.error_response(resp, { 'status': falcon.HTTP_400, 'message': 'Something strange: user id not found' }) def _internalLogin(self, req, resp): credentials = json.loads(req.stream.read()) timezone = req.get_header('X-Timezone') if 'email' not in credentials or 'password' not in credentials: # return bad request pass user_id = self.user_mapper.check_credentials(credentials) if user_id is not None: token = self.token_store.new(user_id, timezone) self.success_response(resp, {'token': token}) else: self.error_response(resp, { 'status': falcon.HTTP_400, 'message': 'Email or password is incorrect.' }) def _check_email(self, req, resp): """Action to check if email of registering user already exists""" email = req.get_param('email') email_exists = False if email is not None: email_exists = self.user_mapper.email_exists(email) resp.status = falcon.HTTP_200 resp.content_type = 'application/json' resp.body = json.dumps({ 'success': 1, 'exists': email_exists })
def __init__(self): self.token_store = TokenStore()