def test_authenticate_client(self):
        request = testing.FakeRequest(headers={})
        # The authorization header is required
        self.assertRaises(HTTPUnauthorized, authenticate_client, request)

        request = testing.FakeRequest(
            headers={'Authorization': 'Advanced foobar'})
        # Only the basic method is allowed
        self.assertRaises(HTTPUnauthorized, authenticate_client, request)

        request = testing.FakeRequest(headers={
                'Authorization': auth_basic_encode('foo', 'bar'),
                }, db=self.db)
        # Invalid user:password
        self.assertRaises(HTTPUnauthorized, authenticate_client, request)

        self.db.applications.insert({
                'client_id': '123456',
                'client_secret': 'secret',
                })
        request = testing.FakeRequest(headers={
                'Authorization': auth_basic_encode('123456', 'secret'),
                }, db=self.db)
        res = authenticate_client(request)
        self.assertEqual(res['client_id'], '123456')
        self.assertEqual(res['client_secret'], 'secret')
    def test_token_endpoint_bad_client_id(self):
        app_id = self.db.applications.insert({
                'client_id': '123456',
                'client_secret': 'secret',
                'callback_url': 'https://example.com/callback',
                'name': 'Example',
                'main_url': 'https://example.com',
                }, safe=True)

        app_id2 = self.db.applications.insert({
                'client_id': '98765',
                'client_secret': 'secret2',
                'callback_url': 'https://example.com/callback2',
                'name': 'Example2',
                'main_url': 'https://example.com',
                }, safe=True)

        user_id = self.db.users.insert({
                'twitter_id': 'twitter1',
                'screen_name': 'John Doe',
                'first_name': 'John',
                'last_name': 'Doe',
                'authorized_apps': [app_id, app_id2],
                }, safe=True)
        self.set_user_cookie(str(user_id))
        self.testapp.get('/oauth2/endpoints/authorization', {
                'response_type': 'code',
                'client_id': '123456',
                })
        grant = self.db.authorization_codes.find_one({
                'scope': DEFAULT_SCOPE,
                'client_id': '123456',
                'user': user_id,
                })
        code = grant['code']

        # Authorize with app2 credentials
        headers = {
            'Authorization': auth_basic_encode('98765', 'secret2'),
            }
        res = self.testapp.post('/oauth2/endpoints/token', {
                'grant_type': 'authorization_code',
                'code': code,
                }, headers=headers, status=401)
        self.assertEqual(res.status, '401 Unauthorized')
    def test_token_endpoint(self):
        # 1. test incorrect requests
        res = self.testapp.post('/oauth2/endpoints/token', {}, status=401)
        self.assertEqual(res.status, '401 Unauthorized')

        headers = {
            'Authorization': auth_basic_encode('123456', 'secret'),
            }

        res = self.testapp.post('/oauth2/endpoints/token', {}, headers=headers, status=401)
        self.assertEqual(res.status, '401 Unauthorized')

        app_id = self.db.applications.insert({
                'client_id': '123456',
                'client_secret': 'secret',
                'callback_url': 'https://example.com/callback',
                'name': 'Example',
                'main_url': 'https://example.com',
                }, safe=True)

        res = self.testapp.post('/oauth2/endpoints/token', {}, headers=headers, status=400)
        self.assertEqual(res.status, '400 Bad Request')
        res.mustcontain('Missing required grant_type')

        res = self.testapp.post('/oauth2/endpoints/token', {
                'grant_type': 'password'
                }, headers=headers, status=501)
        self.assertEqual(res.status, '501 Not Implemented')
        res.mustcontain('Only authorization_code is supported')

        res = self.testapp.post('/oauth2/endpoints/token', {
                'grant_type': 'authorization_code',
                }, headers=headers, status=400)
        self.assertEqual(res.status, '400 Bad Request')
        res.mustcontain('Missing required code')

        res = self.testapp.post('/oauth2/endpoints/token', {
                'grant_type': 'authorization_code',
                'code': 'this-code-does-not-exist',
                }, headers=headers, status=401)
        self.assertEqual(res.status, '401 Unauthorized')

        # 2. Test a valid request

        # first we generate an authorization_code
        user_id = self.db.users.insert({
                'twitter_id': 'twitter1',
                'screen_name': 'John Doe',
                'first_name': 'John',
                'last_name': 'Doe',
                'authorized_apps': [app_id],
                }, safe=True)
        self.set_user_cookie(str(user_id))
        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')
        grant = self.db.authorization_codes.find_one({
                'scope': DEFAULT_SCOPE,
                'client_id': '123456',
                'user': user_id,
                })
        self.assertNotEqual(grant, None)
        code = grant['code']

        # now send the token request
        res = self.testapp.post('/oauth2/endpoints/token', {
                'grant_type': 'authorization_code',
                'code': code,
                }, headers=headers)
        self.assertEqual(res.status, '200 OK')
        self.assertEqual(res.headers['Cache-Control'], 'no-store')
        self.assertEqual(res.headers['Pragma'], 'no-cache')

        # the grant code should be removed
        grant = self.db.authorization_codes.find_one({
                'scope': DEFAULT_SCOPE,
                'client_id': '123456',
                'user': user_id,
                })
        self.assertEqual(grant, None)

        # and an access token should be created
        self.assertEqual(res.json['token_type'], 'bearer')
        self.assertEqual(res.json['expires_in'], 3600)
        self.assertEqual(res.json['scope'], DEFAULT_SCOPE)

        access_code = self.db.access_codes.find_one({
                'code': res.json['access_code'],
                })
        self.assertNotEqual(access_code, None)
 def test_auth_basic_encode(self):
     self.assertEqual(auth_basic_encode('foo', 'bar'),
                      'Basic Zm9vOmJhcg==\n')