def delete_token(self, token): if token in self.tokens: del self.tokens[token] if token in self.nonces: del self.nonces[token] if self.redis: self.redis.delete( "%s:tokens:%s" % (self.redis_prefix, b64sha1sum(token))) self.redis.delete( "%s:nonce:%s" % (self.redis_prefix, b64sha1sum(token)))
def verify_token(self, token, slave_ip): token_data = self.tokens.get(token) if not token_data: if not self.redis: log.info("unknown token %s", token) log.debug("Tokens: %s", self.tokens) return False log.info("couldn't find token data for key %s locally, checking cache", token) token_data = self.redis.get( "%s:tokens:%s" % (self.redis_prefix, b64sha1sum(token))) if not token_data: log.info("not in cache; failing verify_token") return False # Save it for later self.tokens[token] = token_data info = unpack_token_data(token_data) valid_from, valid_to = info['valid_from'], info['valid_to'] now = time.time() if now < valid_from or now > valid_to: log.info("Invalid time window; deleting key") self.delete_token(token) return False if info['slave_ip'] != slave_ip: log.info("Invalid slave ip") self.delete_token(token) return False for secret in self.token_secrets: if verify_token(token_data, token, secret): return True else: return False
def save_nonce(self, token, nonce, expiry): nonce_digest = sign_data(nonce, self.token_secret) self.nonces[token] = nonce_digest if self.redis: log.debug("saving nonce to redis") self.redis.setex("%s:nonce:%s" % (self.redis_prefix, b64sha1sum(token)), nonce_digest, int(expiry - time.time()), ) log.debug("saved nonce to redis")
def save_token(self, token, token_data): self.tokens[token] = token_data valid_to = unpack_token_data(token_data)['valid_to'] if self.redis: log.debug("saving token to redis") self.redis.setex("%s:tokens:%s" % (self.redis_prefix, b64sha1sum(token)), token_data, int(valid_to - time.time()), ) log.debug("saved token to redis") # Set the initial nonce to "" self.save_nonce(token, "", valid_to)
def verify_nonce(self, token, nonce): if self.redis: next_nonce_digest = self.redis.get( "%s:nonce:%s" % (self.redis_prefix, b64sha1sum(token))) else: next_nonce_digest = self.nonces.get(token) if next_nonce_digest is None: return False for secret in self.token_secrets: if sign_data(nonce, secret) == next_nonce_digest: break else: # We tried all secrets and they all failed return False # Generate the next one valid_to = unpack_token_data(self.tokens[token])['valid_to'] next_nonce = b64(os.urandom(16)) self.save_nonce(token, next_nonce, valid_to) return next_nonce