class AuthResource(object): def __init__(self): self.database = Database() self.logger = logging.getLogger("AuthResource") def on_post(self, req, resp): raw_json = req.context['doc'] AUTH_SCHEMA.validate(raw_json) username, password = raw_json.get("username"), raw_json.get("password") if self.is_valid_login(username, password): self.logger.info("Successful login by user %s" % username) resp.body = self.create_auth_doc(username) resp.body["token"] = resp.body["_id"] else: self.logger.warning("Failed login for user %s" % username) raise falcon.HTTPUnauthorized("Invalid credentails", "Failed to authenticate due to invalid username or password") def is_valid_login(self, username, password): user = self.database.get_doc(DB_USER, username, default=None) if user is None: return False hashed_password = hash(password, user[make_private("password_salt")]) return user[make_private("encrypted_password")] == hashed_password def create_auth_doc(self, username): self.logger.info("Creating auth doc for user %s" % username) doc = { "_id": generate_auth_token(), "username": username, "expires": datetime.datetime.now() + CONFIG["auth"]["expiry"] } return self.database.save_doc(DB_AUTH, doc)
class TestSignupAuth(unittest.TestCase): URL = CONFIG["test"]["url"] SIGNUP_URL = urljoin(URL, "users") AUTH_URL = urljoin(URL, "auth") DB_USER = CONFIG["databases"]["user"] def setUp(self): self.db = Database() self.usernames = [] def tearDown(self): for user in self.usernames: delete_user(self.db, user) def get_email_address(self): return "*****@*****.**" def get_username(self): username = ''.join([random.choice(string.ascii_letters) for i in range(20)]) self.usernames.append(username) return username def get_password(self): return "123456" def generate_user(self): return { "username": self.get_username(), "password": self.get_password(), "email": self.get_email_address() } def create_user(self): user = self.generate_user() payload = {"data": user} resp = requests.request("POST", self.SIGNUP_URL, json=payload) self.assertEqual(resp.status_code, 200) return user def test_user_doc(self): user = self.create_user() user_doc = self.db.get_doc(self.DB_USER, user["username"]) self.assertEqual(user_doc.get("password"), None) self.assertEqual(user_doc.get("email"), user.get("email")) def test_private_password(self): user = self.generate_user() payload = {"data": user} resp = requests.request("POST", self.SIGNUP_URL, json=payload) self.assertEqual(resp.status_code, 200) for i in resp.json()["data"].keys(): self.assertNotIn("password", i) def test_signup_twice(self): payload = {"data": self.create_user()} resp = requests.request("POST", self.SIGNUP_URL, json=payload) self.assertEqual(resp.status_code, 400) def auth_request(self, username, password): payload = {"data": { "username": username, "password": password } } return requests.request("POST", self.AUTH_URL, json=payload) def test_signup_and_valid_auth(self): user = self.create_user() resp = self.auth_request(user["username"], user["password"]) self.assertEqual(resp.status_code, 200) self.assertIn("token", resp.json()["data"]) def test_signup_and_invalid_auth(self): user = self.create_user() # Test invalid password resp = self.auth_request(user["username"], user["password"] + "123") self.assertEqual(resp.status_code, 401) # Test invalid username resp2 = self.auth_request(user["username"] + "123", user["password"] + "123") self.assertEqual(resp2.status_code, 401)