def test_some_users(self): authorizator = Authorizator(self.db) app1_id = self.db.applications.insert({ 'client_id': 'app1', 'callback_url': 'https://example.com/callback/1', }) app2_id = self.db.applications.insert({ 'client_id': 'app2', 'callback_url': 'https://example.com/callback/2', }) u1_id = self.db.users.insert({ 'first_name': 'John', 'last_name': 'Doe', 'email': '*****@*****.**', 'authorized_apps': [app1_id, app2_id], }) auths = authorizator.get_user_authorizations({'_id': u1_id}) self.assertEqual(auths.count(), 0) u2_id = self.db.users.insert({ 'first_name': 'John2', 'last_name': 'Doe2', 'email': '*****@*****.**', 'send_passwords_periodically': False, 'authorized_apps': [app1_id], }) auths = authorizator.get_user_authorizations({'_id': u2_id}) self.assertEqual(auths.count(), 0) sys.argv = ['notused', self.conf_file_path, 'new_authorized_apps_collection'] sys.stdout = StringIO() result = migrate() self.assertEqual(result, None) stdout = sys.stdout.getvalue() stdout = sys.stdout.getvalue() expected_output = """Storing authorized app "app1" for user John Doe <*****@*****.**> Storing authorized app "app2" for user John Doe <*****@*****.**> Storing authorized app "app1" for user John2 Doe2 <*****@*****.**> """ self.assertEqual(stdout, expected_output) user1 = self.db.users.find_one({'_id': u1_id}) self.assertFalse('authorized_apps' in user1) auths = authorizator.get_user_authorizations({'_id': u1_id}) self.assertEqual(auths.count(), 2) user2 = self.db.users.find_one({'_id': u2_id}) self.assertFalse('authorized_apps' in user2) auths = authorizator.get_user_authorizations({'_id': u2_id}) self.assertEqual(auths.count(), 1)
def test_already_authorized_app(self): user_id = self._login() self._create_client() authorizator = Authorizator(self.db) auths = authorizator.get_user_authorizations({'_id': user_id}) self.assertEqual(auths.count(), 0) # do an initial authorization res = self.testapp.get('/oauth2/endpoints/authorization', { 'response_type': 'code', 'client_id': '123456', 'redirect_uri': 'https://example.com/callback', }) self.assertEqual(res.status, '200 OK') res = self.testapp.post('/oauth2/endpoints/authorization', { 'submit': 'Authorize', 'response_type': 'code', 'client_id': '123456', 'redirect_uri': 'https://example.com/callback', 'scope': 'read-passwords', }) self.assertEqual(res.status, '302 Found') auths = authorizator.get_user_authorizations({'_id': user_id}) self.assertEqual(auths.count(), 1) # Now do a second authorization res = self.testapp.get('/oauth2/endpoints/authorization', { 'response_type': 'code', 'client_id': '123456', 'redirect_uri': 'https://example.com/callback', }) self.assertEqual(res.status, '302 Found') auths = authorizator.get_user_authorizations({'_id': user_id}) self.assertEqual(auths.count(), 1) grants = self.db.authorization_codes.find({ 'client_id': '123456', 'user': user_id, }) # There are two grants now self.assertEqual(grants.count(), 2) code = grants[1]['code'] location = 'https://example.com/callback?code=%s' % code self.assertEqual(res.location, location)
def test_non_authorized_app_yet(self): user_id = self._login() self._create_client() authorizator = Authorizator(self.db) auths = authorizator.get_user_authorizations({'_id': user_id}) self.assertEqual(auths.count(), 0) res = self.testapp.get('/oauth2/endpoints/authorization', { 'response_type': 'code', 'client_id': '123456', 'redirect_uri': 'https://example.com/callback', }) self.assertEqual(res.status, '200 OK') res.mustcontain('Authorize Application') res.mustcontain('Permissions:') res.mustcontain('Access your passwords') res.mustcontain('Allow access') res.mustcontain('No, thanks') res.mustcontain('You can revoke this authorization in the future.') res = self.testapp.post('/oauth2/endpoints/authorization', { 'submit': 'Authorize', 'response_type': 'code', 'client_id': '123456', 'redirect_uri': 'https://example.com/callback', 'scope': 'read-passwords', }) self.assertEqual(res.status, '302 Found') # Check that the app is authorized now auths = authorizator.get_user_authorizations({'_id': user_id}) self.assertEqual(auths.count(), 1) auth = auths[0] self.assertEqual(auth['redirect_uri'], 'https://example.com/callback') self.assertEqual(auth['response_type'], 'code') self.assertEqual(auth['client_id'], '123456') self.assertEqual(auth['scope'], 'read-passwords') self.assertEqual(auth['user'], user_id) # Check the right redirect url grant = self.db.authorization_codes.find_one({ 'client_id': '123456', 'user': user_id, }) self.assertNotEqual(grant, None) code = grant['code'] location = 'https://example.com/callback?code=%s' % code self.assertEqual(res.location, location)
def merge_users(db, user1, user2): # move all passwords of user2 to user1 db.passwords.update({'owner': user2['_id']}, { '$set': { 'owner': user1['_id'], }, }, multi=True) # move authorized_apps from user2 to user1 authorizator = Authorizator(db) for auth in authorizator.get_user_authorizations(user2): credentials = { 'client_id': auth['client_id'], 'user': user1, 'redirect_uri': auth['redirect_uri'], 'response_type': auth['response_type'], } scopes = auth['scope'].split(' ') authorizator.store_user_authorization(scopes, credentials) authorizator.remove_all_user_authorizations(user2) updates = {} # copy the providers for provider in get_available_providers(): key = provider + '_id' if key in user2 and key not in user1: sets = updates.setdefault('$set', {}) sets[key] = user2[key] db.users.update({'_id': user1['_id']}, updates) # remove user2 db.users.remove(user2['_id'])
class AuthorizatorTests(testing.TestCase): def setUp(self): super(AuthorizatorTests, self).setUp() self.authorizator = Authorizator(self.db) def test_is_app_authorized_no_authorized_apps(self): self.assertFalse(self.authorizator.is_app_authorized([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', })) def test_is_app_authorized_different_client_id(self): self.db.authorized_apps.insert({ 'client_id': 1, 'user': 1, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', 'scope': 'scope1 scope2', }) self.assertFalse(self.authorizator.is_app_authorized([ 'scope1', 'scope2', ], { 'client_id': 2, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', })) def test_is_app_authorized_different_user(self): self.db.authorized_apps.insert({ 'client_id': 1, 'user': 1, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', 'scope': 'scope1 scope2', }) self.assertFalse(self.authorizator.is_app_authorized([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 2}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', })) def test_is_app_authorized_different_redirect_uri(self): self.db.authorized_apps.insert({ 'client_id': 1, 'user': 1, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', 'scope': 'scope1 scope2', }) self.assertFalse(self.authorizator.is_app_authorized([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback-new', 'response_type': 'code', })) def test_is_app_authorized_different_response_type(self): self.db.authorized_apps.insert({ 'client_id': 1, 'user': 1, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', 'scope': 'scope1 scope2', }) self.assertFalse(self.authorizator.is_app_authorized([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'token', })) def test_is_app_authorized_different_scopes(self): self.db.authorized_apps.insert({ 'client_id': 1, 'user': 1, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', 'scope': 'scope1 scope2', }) self.assertFalse(self.authorizator.is_app_authorized([ 'scope1', 'scope2', 'scope3', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', })) def test_is_app_authorized_everything_equal(self): self.db.authorized_apps.insert({ 'client_id': 1, 'user': 1, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', 'scope': 'scope1 scope2', }) self.assertTrue(self.authorizator.is_app_authorized([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', })) def test_store_user_authorization_no_previous_authorization(self): self.assertEqual(self.db.authorized_apps.count(), 0) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', }) self.assertEqual(self.db.authorized_apps.count(), 1) def test_store_user_authorization_previous_authorization(self): self.assertEqual(self.db.authorized_apps.count(), 0) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', }) self.assertEqual(self.db.authorized_apps.count(), 1) # Store the same authorization again self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', }) # still only one record self.assertEqual(self.db.authorized_apps.count(), 1) def test_get_user_authorizations_empty(self): auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 0) def test_get_user_authorizations_one_authorization(self): self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', }) auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 1) self.assertEqual(auths[0]['client_id'], 1) self.assertEqual(auths[0]['redirect_uri'], 'http://example.com/callback') self.assertEqual(auths[0]['response_type'], 'code') self.assertEqual(auths[0]['scope'], 'scope1 scope2') def test_get_user_authorizations_two_authorization(self): self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', }) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 2, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback2', 'response_type': 'code', }) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 2, 'user': {'_id': 2}, 'redirect_uri': 'http://example.com/callback2', 'response_type': 'code', }) auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 2) self.assertEqual(auths[0]['client_id'], 1) self.assertEqual(auths[0]['redirect_uri'], 'http://example.com/callback') self.assertEqual(auths[0]['response_type'], 'code') self.assertEqual(auths[0]['scope'], 'scope1 scope2') self.assertEqual(auths[1]['client_id'], 2) self.assertEqual(auths[1]['redirect_uri'], 'http://example.com/callback2') self.assertEqual(auths[1]['response_type'], 'code') self.assertEqual(auths[1]['scope'], 'scope1 scope2') def test_remove_user_authorization(self): auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 0) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback', 'response_type': 'code', }) auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 1) self.authorizator.remove_user_authorization({'_id': 1}, 1) auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 0) def test_remove_all_user_authorizations(self): auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 0) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 1, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback/1', 'response_type': 'code', }) self.authorizator.store_user_authorization([ 'scope1', 'scope2', ], { 'client_id': 2, 'user': {'_id': 1}, 'redirect_uri': 'http://example.com/callback/2', 'response_type': 'code', }) auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 2) self.authorizator.remove_all_user_authorizations({'_id': 1}) auths = self.authorizator.get_user_authorizations({'_id': 1}) self.assertEqual(auths.count(), 0)
def test_identity_providers(self): # this view required authentication res = self.testapp.get('/identity-providers') self.assertEqual(res.status, '200 OK') res.mustcontain('Log in') authorizator = Authorizator(self.db) # Log in user1_id = self.db.users.insert({ 'twitter_id': 'twitter1', 'screen_name': 'John Doe', 'first_name': 'John', 'last_name': 'Doe', 'email': '*****@*****.**', 'email_verified': True, }) authorizator.store_user_authorization(['scope1'], { 'client_id': 'app1', 'user': {'_id': user1_id}, 'redirect_uri': 'http://example.com/callback/1', 'response_type': 'code', }) authorizator.store_user_authorization(['scope1'], { 'client_id': 'app2', 'user': {'_id': user1_id}, 'redirect_uri': 'http://example.com/callback/2', 'response_type': 'code', }) self.testapp.get('/__login/' + str(user1_id)) self.db.passwords.insert({ 'owner': user1_id, 'password': '******', }) # one account is not enough for merging res = self.testapp.post('/identity-providers', { 'submit': 'Merge my accounts', }, status=400) self.assertEqual(res.status, '400 Bad Request') res.mustcontain('You do not have enough accounts to merge') # so let's create another account with the same email user2_id = self.db.users.insert({ 'google_id': 'google1', 'screen_name': 'John Doe', 'first_name': 'John', 'last_name': 'Doe', 'email': '*****@*****.**', 'email_verified': True, }) authorizator.store_user_authorization(['scope1'], { 'client_id': 'app2', 'user': {'_id': user2_id}, 'redirect_uri': 'http://example.com/callback/2', 'response_type': 'code', }) authorizator.store_user_authorization(['scope1'], { 'client_id': 'app3', 'user': {'_id': user2_id}, 'redirect_uri': 'http://example.com/callback/3', 'response_type': 'code', }) self.db.passwords.insert({ 'owner': user2_id, 'password': '******', }) # now the profile view should say I can merge my accounts res = self.testapp.get('/identity-providers') self.assertEqual(res.status, '200 OK') res.mustcontain('You are registered with the following accounts', 'Merge my accounts', 'If you merge your accounts') # if only one account is selected or fake accounts # are selected nothing is merged res = self.testapp.post('/identity-providers', { 'account-%s' % str(user1_id): 'on', 'account-000000000000000000000000': 'on', 'submit': 'Merge my accounts', }, status=302) self.assertEqual(res.status, '302 Found') self.assertEqual(res.location, 'http://localhost/identity-providers') self.assertEqual(2, self.db.users.count()) self.assertEqual(1, self.db.passwords.find( {'owner': user1_id}).count()) self.assertEqual(1, self.db.passwords.find( {'owner': user2_id}).count()) # let's merge them res = self.testapp.post('/identity-providers', { 'account-%s' % str(user1_id): 'on', 'account-%s' % str(user2_id): 'on', 'submit': 'Merge my accounts', }, status=302) self.assertEqual(res.status, '302 Found') self.assertEqual(res.location, 'http://localhost/identity-providers') # the accounts have been merged self.assertEqual(1, self.db.users.count()) user1_refreshed = self.db.users.find_one({'_id': user1_id}) self.assertEqual(user1_refreshed['google_id'], 'google1') auths = authorizator.get_user_authorizations(user1_refreshed) for real, expected in zip(auths, ['app1', 'app2', 'app3']): self.assertEqual(real['client_id'], expected) user2_refreshed = self.db.users.find_one({'_id': user2_id}) self.assertEqual(user2_refreshed, None) self.assertEqual(2, self.db.passwords.find( {'owner': user1_id}).count())