import unittest try: import mock except ImportError: from unittest import mock import json import urllib.parse import datetime from requests import Session, Response from app import create_app headers = { 'X-CLIENT-ID': 'test_client_id', 'X-CLIENT-SECRET': 'test_client_secret', 'X-REDIRECT-URI': 'https://127.0.0.123:7654/callback', } class MockRequest: def __init__(self): self.headers = [] self.body = '' class MockResponse: def __init__(self, status_code, json_data=None): self.request = MockRequest() self.ok = status_code == 200 self.status_code = status_code self.json = lambda: json_data self.headers = [] self.text = json.dumps(json_data) def mock_request(self, method, url, **kwargs): if method == 'POST' and url == 'https://127.0.0.123:4567/token': return MockResponse(200, {'access_token': '2YotnFZFEjr1zCsicMWpAA', 'token_type': 'Bearer', 'expires_in': 3600, 'refresh_token': 'tGzv3JOkF0XG5Qx2TlKWIA'}) if method == 'GET' and url == 'https://127.0.0.123:4567/userinfo': if kwargs['headers']['Authorization'] != 'Bearer 2YotnFZFEjr1zCsicMWpAA': raise Exception() return MockResponse(200, {'nickname': 'testuser'}) print(repr(method), repr(url), repr(kwargs)) raise Exception() @mock.patch.object(Session, 'request', new=mock_request) class TestCases(unittest.TestCase): def setUp(self): config = { 'TESTING': True, 'DEBUG': True, 'SECRET_KEY': 'DEBUGKEY', 'OAUTH2_AUTH_URL': 'https://127.0.0.123:4567/authorize', 'OAUTH2_TOKEN_URL': 'https://127.0.0.123:4567/token', 'OAUTH2_USERINFO_URL': 'https://127.0.0.123:4567/userinfo', } self.app = create_app(config) self.client = self.app.test_client() self.client.__enter__() # Just do some request so that we can use url_for self.client.get(path='/') def tearDown(self): self.client.__exit__(None, None, None) def test_status(self): r = self.client.get(path='/status', headers=headers) self.assertEqual(r.status_code, 200) self.assertIn('test_client_id', r.data.decode()) self.assertNotIn('test_client_secret', r.data.decode()) def test_auth_no_session(self): r = self.client.get(path='/auth', headers=headers) self.assertEqual(r.status_code, 401) def test_login(self): r = self.client.get(path='/login', query_string={'url': 'https://127.0.0.123:7654/app'}, headers=headers, follow_redirects=False) self.assertEqual(r.status_code, 302) url = urllib.parse.urlparse(r.location) qs = urllib.parse.parse_qs(url.query) self.assertEqual(url.scheme, 'https') self.assertEqual(url.netloc, '127.0.0.123:4567') self.assertEqual(url.path, '/authorize') self.assertEqual(qs['response_type'], ['code']) self.assertEqual(qs['client_id'], ['test_client_id']) self.assertEqual(qs['redirect_uri'], ['https://127.0.0.123:7654/callback']) self.assertGreater(len(qs['state'][0]), 8) with self.client.session_transaction() as session: self.assertEqual(session['state'], qs['state'][0]) self.assertEqual(session['url'], 'https://127.0.0.123:7654/app') def test_callback(self): code = 'testcode' state = 'teststate' with self.client.session_transaction() as session: session['state'] = state session['url'] = 'https://127.0.0.123:7654/app' r = self.client.get(path='/callback', headers=headers, query_string={'code': code, 'state': state}, follow_redirects=False) self.assertEqual(r.status_code, 302) self.assertEqual(r.location, 'https://127.0.0.123:7654/app') with self.client.session_transaction() as session: self.assertGreaterEqual(session['timestamp'], (datetime.datetime.now() - datetime.timedelta(seconds=60)).timestamp()) self.assertEqual(session['client_id'], 'test_client_id') self.assertEqual(session['user_nickname'], 'testuser') self.assertNotIn('state', session) self.assertNotIn('url', session) def test_callback_no_session(self): code = 'testcode' state = 'teststate' r = self.client.get(path='/callback', headers=headers, query_string={'code': code, 'state': state}, follow_redirects=False) self.assertEqual(r.status_code, 302) url = urllib.parse.urlparse(r.location) self.assertEqual(url.path, '/cookiecheck') with self.client.session_transaction() as session: self.assertEqual(session['cookies_enabled'], True) def test_cookiecheck(self): with self.client.session_transaction() as session: session['cookies_enabled'] = True r = self.client.get(path='/cookiecheck', headers=headers, follow_redirects=False) self.assertEqual(r.status_code, 302) url = urllib.parse.urlparse(r.location) self.assertEqual(url.path, '/login') def test_cookiecheck_no_session(self): r = self.client.get(path='/cookiecheck', headers=headers, follow_redirects=False) self.assertEqual(r.status_code, 400) with self.client.session_transaction() as session: self.assertEqual(session['cookies_enabled'], True) def test_auth_session(self): with self.client.session_transaction() as session: session['timestamp'] = datetime.datetime.now().timestamp() session['client_id'] = 'test_client_id' session['user_nickname'] = 'testuser' r = self.client.get(path='/auth', headers=headers) self.assertEqual(r.status_code, 200) self.assertEqual(r.headers['OAUTH-USER-NICKNAME'], 'testuser') def test_auth_session_timeout(self): with self.client.session_transaction() as session: session['timestamp'] = (datetime.datetime.now() - datetime.timedelta(days=3)).timestamp() session['client_id'] = 'test_client_id' session['user_nickname'] = 'testuser' r = self.client.get(path='/auth', headers=headers) self.assertEqual(r.status_code, 401) def test_auth_session_wrong_client(self): with self.client.session_transaction() as session: session['timestamp'] = (datetime.datetime.now() - datetime.timedelta(days=3)).timestamp() session['client_id'] = 'other_client_id' session['user_nickname'] = 'testuser' r = self.client.get(path='/auth', headers=headers) self.assertEqual(r.status_code, 401) def test_logout(self): with self.client.session_transaction() as session: session['timestamp'] = datetime.datetime.now().timestamp() session['client_id'] = 'test_client_id' session['user_nickname'] = 'testuser' r = self.client.get(path='/logout', headers=headers) self.assertEqual(r.status_code, 200) with self.client.session_transaction() as session: self.assertEqual(list(session.keys()), []) def test_logout_no_session(self): r = self.client.get(path='/logout', headers=headers) self.assertEqual(r.status_code, 200) with self.client.session_transaction() as session: self.assertEqual(list(session.keys()), []) def test_logout_redirect(self): with self.client.session_transaction() as session: session['timestamp'] = datetime.datetime.now().timestamp() session['client_id'] = 'test_client_id' session['user_nickname'] = 'testuser' r = self.client.get(path='/logout', headers=headers, query_string={'redirect_url': 'https://127.0.0.123:7654/app/logout'}) self.assertEqual(r.status_code, 302) self.assertEqual(r.location, 'https://127.0.0.123:7654/app/logout') with self.client.session_transaction() as session: self.assertEqual(list(session.keys()), [])