Fix and unify CSRF support across web and API endpoints.
This commit is contained in:
parent
0097daebc2
commit
f060fd6ae0
5 changed files with 53 additions and 28 deletions
43
endpoints/csrf.py
Normal file
43
endpoints/csrf.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
import logging
|
||||
|
||||
from flask import session, request
|
||||
from functools import wraps
|
||||
|
||||
from app import app
|
||||
from auth.auth_context import get_validated_oauth_token
|
||||
from util.http import abort
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_csrf_token():
|
||||
if '_csrf_token' not in session:
|
||||
session['_csrf_token'] = base64.b64encode(os.urandom(48))
|
||||
|
||||
return session['_csrf_token']
|
||||
|
||||
|
||||
def csrf_protect(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
oauth_token = get_validated_oauth_token()
|
||||
if oauth_token is None and request.method != "GET" and request.method != "HEAD":
|
||||
token = session.get('_csrf_token', None)
|
||||
found_token = request.values.get('_csrf_token', None)
|
||||
|
||||
# TODO: add if not token here, once we are sure all sessions have a token.
|
||||
if token != found_token:
|
||||
msg = 'CSRF Failure. Session token was %s and request token was %s'
|
||||
logger.error(msg, token, found_token)
|
||||
abort(403, message='CSRF token was invalid or missing.')
|
||||
|
||||
if not token:
|
||||
logger.warning('No CSRF token in session.')
|
||||
else:
|
||||
logger.debug('Found and validated CSRF token.')
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
app.jinja_env.globals['csrf_token'] = generate_csrf_token
|
Reference in a new issue