Skip to content
Snippets Groups Projects
Commit f6546934 authored by eeonaaah's avatar eeonaaah
Browse files

Merge branch 'backend-csrf' into 'staging'

Csrf prevention

See merge request !58
parents 1745dce7 586f48f8
No related branches found
No related tags found
2 merge requests!62Staging,!58Csrf prevention
Pipeline #5286 passed
...@@ -12,7 +12,8 @@ from main import app, limiter ...@@ -12,7 +12,8 @@ from main import app, limiter
@limiter.limit("100 per minute") @limiter.limit("100 per minute")
def home(): def home():
logging.debug("Front page requested.") logging.debug("Front page requested.")
return render_template('mymap.html') csrfToken = session.get('csrf')
return render_template('mymap.html', csrfToken=csrfToken)
#Route for storing new hive locations #Route for storing new hive locations
...@@ -83,8 +84,9 @@ def delete_location(): ...@@ -83,8 +84,9 @@ def delete_location():
@roles_allowed(roles=['admin']) @roles_allowed(roles=['admin'])
def admin_dashboard(): def admin_dashboard():
user = session.get('user') user = session.get('user')
csrfToken = session.get('csrf')
logging.info(f"Admin {user['email']} logged in") logging.info(f"Admin {user['email']} logged in")
return render_template('admin.html', email=user['email']) return render_template('admin.html', email=user['email'], csrfToken=csrfToken)
# This will work as the login endpoint # This will work as the login endpoint
......
from flask import session, request, Response
from uuid import uuid4
def checkCsrfToken():
"""Checks that a valid csrf token exists in requests that can alter data"""
# no csrf check needed for static requests
if request.endpoint == 'static':
return None
# check if a token exists in session
sessionToken = session.get('csrf')
# issue new one if not
if not sessionToken:
print("issuing new token")
return issueToken()
# no csrf check needed for get requests
if request.method == 'GET':
return None
# get token from request
headerToken = request.headers.get('x-csrf-token')
# check that the two tokens match
if headerToken != sessionToken:
return Response("Invalid csrf key", 403)
def issueToken():
"""Generates a new CSRF token and stores it for current session"""
# issue new if not
sessionToken = str(uuid4())
session['csrf'] = sessionToken
...@@ -149,11 +149,23 @@ def get_user(email): ...@@ -149,11 +149,23 @@ def get_user(email):
return None return None
# def create_test_user(email, roles, client):
# kind = 'UserAccount'
# #set name and kind for key
# key = client.key(kind)
# #Create datastore entity and set key
# datastore_entity = datastore.Entity(key)
# #Update hive data to entity
# datastore_entity.update({
# 'email': email,
# 'roles': roles
# })
# #Store the info to datastore
# client.put(datastore_entity)
...@@ -182,6 +194,7 @@ def _get_datastore_client(default_namespace: bool = False): ...@@ -182,6 +194,7 @@ def _get_datastore_client(default_namespace: bool = False):
namespace='ns_test', namespace='ns_test',
credentials=None credentials=None
) )
return client return client
......
import os
class Config(object):
DEBUG = False
TESTING = False
class ProductionConfig(Config):
pass
class DevConfig(Config):
DEBUG = True
FLASK_ENV = os.getenv("DEV")
DATASTORE_EMULATOR_HOST = os.getenv("DATASTORE_EMULATOR_HOST")
DATASTORE_EMULATOR_HOST_PATH = os.getenv("DATASTORE_EMULATOR_HOST_PATH")
class TestingConfig(Config):
TESTING = True
FLASK_ENV = os.getenv("DEV")
DATASTORE_EMULATOR_HOST = os.getenv("DATASTORE_EMULATOR_HOST")
DATASTORE_EMULATOR_HOST_PATH = os.getenv("DATASTORE_EMULATOR_HOST_PATH")
\ No newline at end of file
...@@ -13,6 +13,7 @@ from opencensus.trace.samplers import ProbabilitySampler ...@@ -13,6 +13,7 @@ from opencensus.trace.samplers import ProbabilitySampler
from flask_babel import Babel from flask_babel import Babel
from flask_limiter import Limiter from flask_limiter import Limiter
from flask_limiter.util import get_remote_address from flask_limiter.util import get_remote_address
from api.services.csrf import checkCsrfToken
app = Flask(__name__) app = Flask(__name__)
...@@ -56,6 +57,8 @@ def main(): ...@@ -56,6 +57,8 @@ def main():
sampler=ProbabilitySampler(rate=1.0) sampler=ProbabilitySampler(rate=1.0)
) )
app.before_request(checkCsrfToken)
from api.routes import * from api.routes import *
# app.config.from_object("config.DevConfig") # app.config.from_object("config.DevConfig")
......
...@@ -42,6 +42,7 @@ async function saveLocation(data) { ...@@ -42,6 +42,7 @@ async function saveLocation(data) {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'x-csrf-token': csrfToken
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
...@@ -64,6 +65,7 @@ async function deleteLocation(data) { ...@@ -64,6 +65,7 @@ async function deleteLocation(data) {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'x-csrf-token': csrfToken
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
...@@ -97,6 +99,7 @@ async function editLocation(data) { ...@@ -97,6 +99,7 @@ async function editLocation(data) {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'x-csrf-token': csrfToken
}, },
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<title>{{_("Admin interface")}}</title> <title>{{_("Admin interface")}}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script>var csrfToken = "{{ csrfToken }}"</script>
<script type = "module" src="{{ url_for('static', filename='admin.js') }}"></script> <script type = "module" src="{{ url_for('static', filename='admin.js') }}"></script>
</head> </head>
<body> <body>
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
crossorigin="" crossorigin=""
/> />
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" />
<script>var csrfToken = "{{ csrfToken }}"</script>
<script <script
src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment