Escape untrusted content before displaying it.
Reviewed in https://codereview.appspot.com/6460120/.
This commit is contained in:
@@ -20,6 +20,7 @@ Utilities for making it easier to use OAuth 2.0 on Google App Engine.
|
||||
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
|
||||
|
||||
import base64
|
||||
import cgi
|
||||
import httplib2
|
||||
import logging
|
||||
import os
|
||||
@@ -51,6 +52,18 @@ OAUTH2CLIENT_NAMESPACE = 'oauth2client#ns'
|
||||
XSRF_MEMCACHE_ID = 'xsrf_secret_key'
|
||||
|
||||
|
||||
def _safe_html(s):
|
||||
"""Escape text to make it safe to display.
|
||||
|
||||
Args:
|
||||
s: string, The text to escape.
|
||||
|
||||
Returns:
|
||||
The escaped text as a string.
|
||||
"""
|
||||
return cgi.escape(s, quote=1).replace("'", ''')
|
||||
|
||||
|
||||
class InvalidClientSecretsError(Exception):
|
||||
"""The client_secrets.json file is malformed or missing required fields."""
|
||||
|
||||
@@ -417,7 +430,7 @@ class OAuth2Decorator(object):
|
||||
|
||||
def _display_error_message(self, request_handler):
|
||||
request_handler.response.out.write('<html><body>')
|
||||
request_handler.response.out.write(self._message)
|
||||
request_handler.response.out.write(_safe_html(self._message))
|
||||
request_handler.response.out.write('</body></html>')
|
||||
|
||||
def oauth_required(self, method):
|
||||
@@ -578,7 +591,7 @@ class OAuth2Decorator(object):
|
||||
if error:
|
||||
errormsg = self.request.get('error_description', error)
|
||||
self.response.out.write(
|
||||
'The authorization request failed: %s' % errormsg)
|
||||
'The authorization request failed: %s' % _safe_html(errormsg))
|
||||
else:
|
||||
user = users.get_current_user()
|
||||
decorator._create_flow(self)
|
||||
|
||||
@@ -331,7 +331,10 @@ class DecoratorTests(unittest.TestCase):
|
||||
webapp2.Route(r'/bar_path/<year:\d{4}>/<month:\d{2}>',
|
||||
handler=TestAwareHandler, name='bar')],
|
||||
debug=True)
|
||||
self.app = TestApp(application)
|
||||
self.app = TestApp(application, extra_environ={
|
||||
'wsgi.url_scheme': 'http',
|
||||
'HTTP_HOST': 'localhost',
|
||||
})
|
||||
users.get_current_user = user_mock()
|
||||
self.httplib2_orig = httplib2.Http
|
||||
httplib2.Http = Http2Mock
|
||||
@@ -343,7 +346,7 @@ class DecoratorTests(unittest.TestCase):
|
||||
def test_required(self):
|
||||
# An initial request to an oauth_required decorated path should be a
|
||||
# redirect to start the OAuth dance.
|
||||
response = self.app.get('/foo_path')
|
||||
response = self.app.get('http://localhost/foo_path')
|
||||
self.assertTrue(response.status.startswith('302'))
|
||||
q = parse_qs(response.headers['Location'].split('?', 1)[1])
|
||||
self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0])
|
||||
@@ -425,7 +428,7 @@ class DecoratorTests(unittest.TestCase):
|
||||
|
||||
def test_aware(self):
|
||||
# An initial request to an oauth_aware decorated path should not redirect.
|
||||
response = self.app.get('/bar_path/2012/01')
|
||||
response = self.app.get('http://localhost/bar_path/2012/01')
|
||||
self.assertEqual('Hello World!', response.body)
|
||||
self.assertEqual('200 OK', response.status)
|
||||
self.assertEqual(False, self.decorator.has_credentials())
|
||||
@@ -471,10 +474,10 @@ class DecoratorTests(unittest.TestCase):
|
||||
response = self.app.get('/bar_path/2012/01')
|
||||
url = self.decorator.authorize_url()
|
||||
response = self.app.get('/oauth2callback', {
|
||||
'error': 'BadStuffHappened'
|
||||
'error': 'Bad<Stuff>Happened\''
|
||||
})
|
||||
self.assertEqual('200 OK', response.status)
|
||||
self.assertTrue('BadStuffHappened' in response.body)
|
||||
self.assertTrue('Bad<Stuff>Happened'' in response.body)
|
||||
|
||||
def test_kwargs_are_passed_to_underlying_flow(self):
|
||||
decorator = OAuth2Decorator(client_id='foo_client_id',
|
||||
|
||||
Reference in New Issue
Block a user