def test_login_info(client): # Make sure we can get user info when logged in already. json_authenticate(client) response = client.get("/login", headers={"Content-Type": "application/json"}) assert response.status_code == 200 assert response.json["response"]["user"]["email"] == "*****@*****.**" assert "last_update" in response.json["response"]["user"] response = client.get("/login", headers={"Accept": "application/json"}) assert response.status_code == 200 assert response.json["response"]["user"]["email"] == "*****@*****.**" assert "last_update" in response.json["response"]["user"]
def test_change_token_uniquifier(app): # make sure that existing token no longer works once we change the token uniquifier from sqlalchemy import Column, String from flask_sqlalchemy import SQLAlchemy from flask_security.models import fsqla_v2 as fsqla from flask_security import Security, SQLAlchemyUserDatastore app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:" db = SQLAlchemy(app) fsqla.FsModels.set_db_info(db) class Role(db.Model, fsqla.FsRoleMixin): pass class User(db.Model, fsqla.FsUserMixin): fs_token_uniquifier = Column(String(64), unique=True, nullable=False) with app.app_context(): db.create_all() ds = SQLAlchemyUserDatastore(db, User, Role) app.security = Security(app, datastore=ds) with app.app_context(): ds.create_user( email="*****@*****.**", password=hash_password("password"), ) ds.commit() client_nc = app.test_client(use_cookies=False) response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token) # now change uniquifier with app.test_request_context("/"): user = app.security.datastore.find_user(email="*****@*****.**") app.security.datastore.reset_user_access(user) app.security.datastore.commit() verify_token(client_nc, token, status=401) # get new token and verify it works response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token)
def test_change_invalidates_auth_token(app, client): # if change password, by default that should invalidate auth tokens response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] headers = {"Authentication-Token": token} # make sure can access restricted page response = client.get("/token", headers=headers) assert b"Token Authentication" in response.data response = client.post( "/change", data={ "password": "******", "new_password": "******", "new_password_confirm": "new strong password", }, follow_redirects=True, ) assert response.status_code == 200 # authtoken should now be invalid response = client.get("/token", headers=headers) assert response.status_code == 302 assert response.headers[ "Location"] == "http://localhost/login?next=%2Ftoken"
def test_sending_auth_token_with_json(client): response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] data = '{"auth_token": "%s"}' % token response = client.post("/token", data=data, headers={"Content-Type": "application/json"}) assert b"Token Authentication" in response.data
def test_auth_uniquifier(app): # If add fs_token_uniquifier to user model - change password shouldn't invalidate # auth tokens. from sqlalchemy import Column, String from flask_sqlalchemy import SQLAlchemy from flask_security.models import fsqla_v2 as fsqla from flask_security import Security, SQLAlchemyUserDatastore app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:" db = SQLAlchemy(app) fsqla.FsModels.set_db_info(db) class Role(db.Model, fsqla.FsRoleMixin): pass class User(db.Model, fsqla.FsUserMixin): fs_token_uniquifier = Column(String(64), unique=True, nullable=False) with app.app_context(): db.create_all() ds = SQLAlchemyUserDatastore(db, User, Role) app.security = Security(app, datastore=ds) with app.app_context(): ds.create_user( email="*****@*****.**", password=hash_password("password"), ) ds.commit() client = app.test_client() # standard login with auth token response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] headers = {"Authentication-Token": token} # make sure can access restricted page response = client.get("/token", headers=headers) assert b"Token Authentication" in response.data # change password response = client.post( "/change", data={ "password": "******", "new_password": "******", "new_password_confirm": "new strong password", }, follow_redirects=True, ) assert response.status_code == 200 # authtoken should still be valid response = client.get("/token", headers=headers) assert response.status_code == 200
def test_change_uniquifier(app, client_nc): # make sure that existing token no longer works once we change the uniquifier response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token) # now change uniquifier with app.test_request_context("/"): user = app.security.datastore.find_user(email="*****@*****.**") app.security.datastore.reset_user_access(user) app.security.datastore.commit() verify_token(client_nc, token, status=401) # get new token and verify it works response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token)
def test_authn_freshness_nc(app, client_nc, get_message): # If don't send session cookie - then freshness always fails @auth_required(within=30) def myview(): return Response(status=200) app.add_url_rule("/myview", view_func=myview, methods=["GET"]) response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] h = {"Authentication-Token": token} # This should fail - should be a redirect response = client_nc.get("/myview", headers=h, follow_redirects=False) assert response.status_code == 302 assert (response.location == "http://localhost/verify?next=http%3A%2F%2Flocalhost%2Fmyview")
def test_token_change(app, client_nc): # Verify can change password using token auth only login_response = json_authenticate(client_nc) token = login_response.json["response"]["user"]["authentication_token"] data = dict( password="******", new_password="******", new_password_confirm="new strong password", ) response = client_nc.post( "/change?include_auth_token=1", json=data, headers={"Content-Type": "application/json", "Authentication-Token": token}, ) assert response.status_code == 200 assert "authentication_token" in response.json["response"]["user"]
def test_token_query(in_app_context): # Verify that when authenticating with auth token (and not session) # that there is just one DB query to get user. app = in_app_context populate_data(app) client_nc = app.test_client(use_cookies=False) response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] current_nqueries = get_num_queries(app.security.datastore) response = client_nc.get( "/token", headers={"Content-Type": "application/json", "Authentication-Token": token}, ) assert response.status_code == 200 end_nqueries = get_num_queries(app.security.datastore) assert current_nqueries is None or end_nqueries == (current_nqueries + 1)
def test_null_token_uniquifier(app): # If existing record has a null fs_token_uniquifier, should be set on first use. from sqlalchemy import Column, String from flask_sqlalchemy import SQLAlchemy from flask_security.models import fsqla_v2 as fsqla from flask_security import Security, SQLAlchemyUserDatastore app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:" db = SQLAlchemy(app) fsqla.FsModels.set_db_info(db) class Role(db.Model, fsqla.FsRoleMixin): pass class User(db.Model, fsqla.FsUserMixin): fs_token_uniquifier = Column(String(64), unique=True, nullable=True) with app.app_context(): db.create_all() ds = SQLAlchemyUserDatastore(db, User, Role) app.security = Security(app, datastore=ds) with app.app_context(): ds.create_user( email="*****@*****.**", password=hash_password("password"), ) ds.commit() # manually null out fs_token_uniquifier user = ds.find_user(email="*****@*****.**") user.fs_token_uniquifier = None ds.put(user) ds.commit() client_nc = app.test_client(use_cookies=False) response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token)
def test_username(app, client, get_message): data = dict( email="*****@*****.**", username="******", password="******", ) response = client.post("/register", json=data, headers={"Content-Type": "application/json"}) assert response.headers["Content-Type"] == "application/json" assert response.status_code == 200 logout(client) # login using historic - email field... response = json_authenticate(client, email="dude", password="******") assert response.status_code == 200 logout(client) # login using us-signin response = client.post( "/us-signin", data=dict(identity="dude", passcode="awesome sunset"), follow_redirects=True, ) assert b"Welcome [email protected]" in response.data # make sure username is unique logout(client) data = dict( email="*****@*****.**", username="******", password="******", ) response = client.post("/register", json=data, headers={"Content-Type": "application/json"}) assert response.status_code == 400 assert (get_message("USERNAME_ALREADY_ASSOCIATED", username="******") == response.json["response"]["errors"]["username"][0].encode())
def test_auth_token_speed(app, client_nc): # To run with old algorithm you have to comment out fs_uniquifier check in UserMixin import timeit response = json_authenticate(client_nc) token = response.json["response"]["user"]["authentication_token"] def time_get(): rp = client_nc.get( "/login", data={}, headers={ "Content-Type": "application/json", "Authentication-Token": token }, ) assert rp.status_code == 200 t = timeit.timeit(time_get, number=50) print("Time for 50 iterations: ", t)
def test_inactive_forbids_token(app, client_nc, get_message): """Make sure that existing token doesn't work after user marked inactive """ response = json_authenticate(client_nc) assert response.status_code == 200 token = response.json["response"]["user"]["authentication_token"] headers = {"Authentication-Token": token} # make sure can access restricted page response = client_nc.get("/token", headers=headers) assert b"Token Authentication" in response.data # deactivate matt with app.test_request_context("/"): user = app.security.datastore.find_user(email="*****@*****.**") app.security.datastore.deactivate_user(user) app.security.datastore.commit() response = client_nc.get("/token", content_type="application/json", headers=headers) assert response.status_code == 401
def test_session_query(in_app_context): # Verify that when authenticating with auth token (but also sending session) # that there are 2 DB queries to get user. # This is since the session will load one - but auth_token_required needs to # verify that the TOKEN is valid (and it is possible that the user_id in the # session is different that the one in the token (huh?) app = in_app_context populate_data(app) client = app.test_client() response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] current_nqueries = get_num_queries(app.security.datastore) response = client.get( "/token", headers={"Content-Type": "application/json", "Authentication-Token": token}, ) assert response.status_code == 200 end_nqueries = get_num_queries(app.security.datastore) assert current_nqueries is None or end_nqueries == (current_nqueries + 2)
def test_multi_auth_token(client): response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] response = client.get("/multi_auth?auth_token=" + token) assert b"Token" in response.data
def test_token_auth_via_header_valid_token(client): response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] headers = {"Authentication-Token": token} response = client.get("/token", headers=headers) assert b"Token Authentication" in response.data
def test_token_auth_via_querystring_valid_token(client): response = json_authenticate(client) token = response.json["response"]["user"]["authentication_token"] response = client.get("/token?auth_token=" + token) assert b"Token Authentication" in response.data
def test_invalid_json_auth(client): response = json_authenticate(client, password="******") assert b'"code": 400' in response.data
def test_ok_json_auth(client): response = json_authenticate(client) assert response.json["meta"]["code"] == 200 assert "authentication_token" in response.json["response"]["user"]