1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Decorator that validates XSRF tokens.""" 6 7import os 8 9from google.appengine.api import users 10from google.appengine.ext import ndb 11 12from oauth2client import xsrfutil 13 14 15class XsrfSecretKey(ndb.Model): 16 """Stores a secret XSRF key for the site.""" 17 token = ndb.StringProperty(indexed=False) 18 19 20def _ValidateToken(token, user): 21 """Validates an XSRF token generated by GenerateXsrfToken.""" 22 return xsrfutil.validate_token( 23 _GetSecretKey(), token, user_id=user.user_id(), action_id='') 24 25 26def GenerateToken(user): 27 return xsrfutil.generate_token( 28 _GetSecretKey(), user_id=user.user_id(), action_id='') 29 30 31def _GenerateNewSecretKey(): 32 """Returns a random XSRF secret key.""" 33 return str(os.urandom(16).encode('hex')) 34 35 36def _GetSecretKey(): 37 """Gets or creates the secret key to use for validating XSRF tokens.""" 38 key_entity = ndb.Key('XsrfSecretKey', 'site').get() 39 if not key_entity: 40 key_entity = XsrfSecretKey(id='site', token=_GenerateNewSecretKey()) 41 key_entity.put() 42 return key_entity.token.encode('ascii', 'ignore') 43 44 45def TokenRequired(handler_method): 46 """A decorator to require that the XSRF token be validated for the handler.""" 47 48 def CheckToken(self, *args, **kwargs): 49 user = users.get_current_user() 50 token = str(self.request.get('xsrf_token')) 51 if not user or not _ValidateToken(token, user): 52 self.abort(403) 53 handler_method(self, *args, **kwargs) 54 55 return CheckToken 56