1"""Client authentication tests across all endpoints. 2 3Client authentication in OAuth2 serve two purposes, to authenticate 4confidential clients and to ensure public clients are in fact public. The 5latter is achieved with authenticate_client_id and the former with 6authenticate_client. 7 8We make sure authentication is done by requiring a client object to be set 9on the request object with a client_id parameter. The client_id attribute 10prevents this check from being circumvented with a client form parameter. 11""" 12from __future__ import absolute_import, unicode_literals 13import json 14import mock 15 16from .test_utils import get_fragment_credentials 17from ....unittest import TestCase 18 19from oauthlib.oauth2 import RequestValidator 20from oauthlib.oauth2 import WebApplicationServer, MobileApplicationServer 21from oauthlib.oauth2 import LegacyApplicationServer, BackendApplicationServer 22 23 24class ClientAuthenticationTest(TestCase): 25 26 def inspect_client(self, request, refresh_token=False): 27 if not request.client or not request.client.client_id: 28 raise ValueError() 29 return 'abc' 30 31 def setUp(self): 32 self.validator = mock.MagicMock(spec=RequestValidator) 33 self.validator.get_default_redirect_uri.return_value = 'http://i.b./path' 34 self.web = WebApplicationServer(self.validator, 35 token_generator=self.inspect_client) 36 self.mobile = MobileApplicationServer(self.validator, 37 token_generator=self.inspect_client) 38 self.legacy = LegacyApplicationServer(self.validator, 39 token_generator=self.inspect_client) 40 self.backend = BackendApplicationServer(self.validator, 41 token_generator=self.inspect_client) 42 43 def set_client(self, request): 44 request.client = mock.MagicMock() 45 request.client.client_id = 'mocked' 46 return True 47 48 def set_client_id(self, client_id, request): 49 request.client = mock.MagicMock() 50 request.client.client_id = 'mocked' 51 return True 52 53 def set_username(self, username, password, client, request): 54 request.client = mock.MagicMock() 55 request.client.client_id = 'mocked' 56 return True 57 58 def test_client_id_authentication(self): 59 token_uri = 'http://example.com/path' 60 61 # authorization code grant 62 self.validator.authenticate_client.return_value = False 63 self.validator.authenticate_client_id.return_value = False 64 _, body, _ = self.web.create_token_response(token_uri, 65 body='grant_type=authorization_code&code=mock') 66 self.assertEqual(json.loads(body)['error'], 'invalid_client') 67 68 self.validator.authenticate_client_id.return_value = True 69 self.validator.authenticate_client.side_effect = self.set_client 70 _, body, _ = self.web.create_token_response(token_uri, 71 body='grant_type=authorization_code&code=mock') 72 self.assertIn('access_token', json.loads(body)) 73 74 # implicit grant 75 auth_uri = 'http://example.com/path?client_id=abc&response_type=token' 76 self.assertRaises(ValueError, self.mobile.create_authorization_response, 77 auth_uri, scopes=['random']) 78 79 self.validator.validate_client_id.side_effect = self.set_client_id 80 h, _, s = self.mobile.create_authorization_response(auth_uri, scopes=['random']) 81 self.assertEqual(302, s) 82 self.assertIn('Location', h) 83 self.assertIn('access_token', get_fragment_credentials(h['Location'])) 84 85 def test_custom_authentication(self): 86 token_uri = 'http://example.com/path' 87 88 # authorization code grant 89 self.assertRaises(NotImplementedError, 90 self.web.create_token_response, token_uri, 91 body='grant_type=authorization_code&code=mock') 92 93 # password grant 94 self.validator.authenticate_client.return_value = True 95 self.assertRaises(NotImplementedError, 96 self.legacy.create_token_response, token_uri, 97 body='grant_type=password&username=abc&password=secret') 98 99 # client credentials grant 100 self.validator.authenticate_client.return_value = True 101 self.assertRaises(NotImplementedError, 102 self.backend.create_token_response, token_uri, 103 body='grant_type=client_credentials') 104