def test_purge_expired_tokens(self): """ Generate tokens with current time as expiration date/time. That is, tokens are expired as soon as they are generated. """ for user in self.users: token = generate_user_auth_token(user, 'password hash', timeout=0) auth_token = lookup_user_auth_token(user, token) self.assertEqual(None, auth_token) # As expired tokens are purged from the DB just before # they are generated, the above should leave us with one # expired token in the DB query = Session.gql("WHERE expire_date <= :1", api.utcnow()) expired_tokens = query.count() self.assertEqual(1, expired_tokens) # Generate another token to trigger cache purging which # should leave us with no expired sessions in the DB (as # this token is generated with a future expiration date.) token = generate_user_auth_token('fake user', 'password hash') query = Session.gql("WHERE expire_date <= :1", api.utcnow()) expired_tokens = query.count() self.assertEqual(0, expired_tokens)
def generate_user_auth_token(nick, password, timeout=(14 * 24 * 60 * 60)): """ Generates a user authentication token and stores it in the database for later retrieval. Why store tokens in the database? Because GAE flushes memcache quite aggressively and this was causing users to be logged out much more frequently than was acceptable. """ # Clear cache of expired tokens purge_expired_user_auth_token_keys() token = util.hash_generic(util.generate_uuid()) key = generate_user_auth_token_key(nick, token) # Set an expiration date to enable us to purge old, inactive # sessions from the database. Cookie expiration dates are what # actually govern how long sessions last. expire_date = (api.utcnow() + datetime.timedelta(seconds=timeout)) session = Session(key_name=key, session_data=db.Blob(password.encode("utf-8")), expire_date=expire_date) session.put() return token
def save(self, must_create=False): if must_create and self.exists(self.session_key): raise base.CreateError session = Session( key_name='k:' + self.session_key, session_data = self.encode(self._session), expire_date = self.get_expiry_date()) session.put()
def _get_session(self, session_key): session = Session.get_by_key_name('k:' + session_key) if session: if session.expire_date > datetime.now(): return session session.delete() return None
def lookup_user_auth_token(nick, token): """ Look up a user authentication token from the database cache. """ key = generate_user_auth_token_key(nick, token) user_auth_token_blob = Session.get_by_key_name(key) if not user_auth_token_blob: return None elif user_auth_token_blob.expire_date <= api.utcnow(): return None else: user_auth_token = user_auth_token_blob.session_data.decode("utf-8") return user_auth_token
def purge_expired_user_auth_token_keys(): """ Remove expired tokens from the database. """ #TODO: Remove hard coded limit limit = 10 try: query = Session.gql("WHERE expire_date <= :1", api.utcnow()) expired_tokens = query.count() if expired_tokens: db.delete(query.fetch(limit)) logging.info("Removed %d expired user authentication " "tokens (%d remaining)", min(limit, expired_tokens), max(0, expired_tokens-limit)) except Exception, e: logging.exception('Unhandled exception while removing expired tokens')
def exists(self, session_key): return Session.get_by_key_name('k:' + session_key) is not None
def save(self): session = Session( key_name='k:' + self.session_key, session_data = self.encode(self._session), expire_date = self.get_expiry_date()) session.put()
def save(self): session = Session(key_name='k:' + self.session_key, session_data=self.encode(self._session), expire_date=self.get_expiry_date()) session.put()