You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
15 KiB
374 lines
15 KiB
# -*- coding: utf-8 -*-
|
|
# Copyright 2016 SYLEAM
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
|
|
import base64
|
|
import json
|
|
import logging
|
|
from .common_test_controller import OAuthProviderControllerTransactionCase
|
|
from .common_test_oauth_provider_controller import \
|
|
TestOAuthProviderRefreshTokenController, \
|
|
TestOAuthProviderTokeninfoController, \
|
|
TestOAuthProviderUserinfoController, \
|
|
TestOAuthProviderOtherinfoController, \
|
|
TestOAuthProviderRevokeTokenController
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TestOAuthProviderController(
|
|
OAuthProviderControllerTransactionCase,
|
|
TestOAuthProviderRefreshTokenController,
|
|
TestOAuthProviderTokeninfoController,
|
|
TestOAuthProviderUserinfoController,
|
|
TestOAuthProviderOtherinfoController,
|
|
TestOAuthProviderRevokeTokenController):
|
|
def setUp(self):
|
|
super(TestOAuthProviderController, self).setUp('legacy application')
|
|
|
|
def test_token_error_missing_arguments(self):
|
|
""" Check /oauth2/token without any argument
|
|
|
|
Must return an unsupported_grant_type error
|
|
"""
|
|
response = self.post_request('/oauth2/token')
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client_id'})
|
|
|
|
def test_token_error_wrong_grant_type(self):
|
|
""" Check /oauth2/token with an invalid grant type
|
|
|
|
Must return an unsupported_grant_type error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'grant_type': 'Wrong grant type',
|
|
'username': 'Wrong username',
|
|
'password': 'Wrong password',
|
|
})
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'unsupported_grant_type'})
|
|
|
|
def test_token_error_missing_username(self):
|
|
""" Check /oauth2/token without username
|
|
|
|
Must return an invalid_request error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'grant_type': self.client.grant_type,
|
|
})
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(json.loads(response.data), {
|
|
'error': 'invalid_request',
|
|
'error_description': 'Request is missing username parameter.',
|
|
})
|
|
|
|
def test_token_error_missing_password(self):
|
|
""" Check /oauth2/token without password
|
|
|
|
Must return an invalid_request error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'grant_type': self.client.grant_type,
|
|
'username': 'Wrong username',
|
|
})
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(json.loads(response.data), {
|
|
'error': 'invalid_request',
|
|
'error_description': 'Request is missing password parameter.',
|
|
})
|
|
|
|
def test_token_error_missing_client_id(self):
|
|
""" Check /oauth2/token without client
|
|
|
|
Must return an unauthorized_client error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': self.client.grant_type,
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client_id'})
|
|
|
|
def test_token_error_wrong_client_identifier(self):
|
|
""" Check /oauth2/token with a wrong client identifier
|
|
|
|
Must return an invalid_client_id error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': self.client.grant_type,
|
|
'client_id': 'Wrong client identifier',
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client_id'})
|
|
|
|
def test_token_error_wrong_username(self):
|
|
""" Check /oauth2/token with a wrong username
|
|
|
|
Must return an invalid_grant error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': self.client.grant_type,
|
|
'client_id': self.client.identifier,
|
|
'username': 'Wrong username',
|
|
'password': 'demo',
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(json.loads(response.data), {
|
|
'error': 'invalid_grant',
|
|
'error_description': 'Invalid credentials given.',
|
|
})
|
|
|
|
def test_token_error_wrong_password(self):
|
|
""" Check /oauth2/token with a wrong password
|
|
|
|
Must return an invalid_grant error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': self.client.grant_type,
|
|
'client_id': self.client.identifier,
|
|
'username': self.user.login,
|
|
'password': 'Wrong password',
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(json.loads(response.data), {
|
|
'error': 'invalid_grant',
|
|
'error_description': 'Invalid credentials given.',
|
|
})
|
|
|
|
def test_token_error_wrong_client_id(self):
|
|
""" Check /oauth2/token with a wrong client id
|
|
|
|
Must return an invalid_client_id error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': self.client.grant_type,
|
|
'client_id': 'Wrong client id',
|
|
'scope': self.client.scope_ids[0].code,
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client_id'})
|
|
|
|
def test_token_error_missing_refresh_token(self):
|
|
""" Check /oauth2/token in refresh token mode without refresh token
|
|
|
|
Must return an invalid_request error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': 'refresh_token',
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
})
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(json.loads(response.data), {
|
|
'error': 'invalid_request',
|
|
'error_description': 'Missing refresh token parameter.',
|
|
})
|
|
|
|
def test_token_error_invalid_refresh_token(self):
|
|
""" Check /oauth2/token in refresh token mode with an invalid refresh token
|
|
|
|
Must return an invalid_grant error
|
|
"""
|
|
response = self.post_request('/oauth2/token', data={
|
|
'grant_type': 'refresh_token',
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'refresh_token': 'Wrong refresh token',
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(json.loads(response.data), {'error': 'invalid_grant'})
|
|
|
|
def test_token_with_missing_secret(self):
|
|
""" Check client authentication without the secret provided
|
|
|
|
Must return an invalid_client error
|
|
"""
|
|
# Define a secret for the client
|
|
self.client.secret = 'OAuth Client secret'
|
|
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
})
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client'})
|
|
|
|
def test_token_with_unexpected_secret(self):
|
|
""" Check client authentication with an unexpected secret provided
|
|
|
|
Must return an invalid_client error
|
|
"""
|
|
# Don't define a secret for the client
|
|
auth_string = base64.b64encode(
|
|
'{client.identifier}:secret'.format(client=self.client))
|
|
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
}, headers=[(
|
|
'Authorization',
|
|
'Basic {auth_string}'.format(auth_string=auth_string)),
|
|
])
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client'})
|
|
|
|
def test_token_with_wrong_secret(self):
|
|
""" Check client authentication with a wrong secret
|
|
|
|
Must return an invalid_client error
|
|
"""
|
|
# Define a secret for the client
|
|
self.client.secret = 'OAuth Client secret'
|
|
auth_string = base64.b64encode(
|
|
'{client.identifier}:secret'.format(client=self.client))
|
|
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
}, headers=[(
|
|
'Authorization',
|
|
'Basic {auth_string}'.format(auth_string=auth_string)),
|
|
])
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client'})
|
|
|
|
def test_token_with_secret(self):
|
|
""" Check client authentication from Authorization header """
|
|
# Define a secret for the client
|
|
self.client.secret = 'OAuth Client secret'
|
|
auth_string = base64.b64encode(
|
|
'{client.identifier}:{client.secret}'.format(client=self.client))
|
|
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
}, headers=[(
|
|
'Authorization',
|
|
'Basic {auth_string}'.format(auth_string=auth_string)),
|
|
])
|
|
response_data = json.loads(response.data)
|
|
# A new token should have been generated
|
|
# We can safely pick the latest generated token here, because no other
|
|
# token could have been generated during the test
|
|
token = self.env['oauth.provider.token'].search([
|
|
('client_id', '=', self.client.id),
|
|
], order='id DESC', limit=1)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(token.token, response_data['access_token'])
|
|
self.assertEqual(token.token_type, response_data['token_type'])
|
|
self.assertEqual(token.refresh_token, response_data['refresh_token'])
|
|
self.assertEqual(token.scope_ids, self.client.scope_ids[0])
|
|
self.assertEqual(token.user_id, self.user)
|
|
|
|
def test_token_with_wrong_non_basic_authorization(self):
|
|
""" Check client authentication with a non-Basic Authorization header
|
|
|
|
Must generate a token : Non basic authorization headers are ignored
|
|
"""
|
|
# Don't define a secret for the client
|
|
auth_string = base64.b64encode(
|
|
'{client.identifier}:secret'.format(client=self.client))
|
|
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
}, headers=[(
|
|
'Authorization',
|
|
'Digest {auth_string}'.format(auth_string=auth_string)),
|
|
])
|
|
response_data = json.loads(response.data)
|
|
# A new token should have been generated
|
|
# We can safely pick the latest generated token here, because no other
|
|
# token could have been generated during the test
|
|
token = self.env['oauth.provider.token'].search([
|
|
('client_id', '=', self.client.id),
|
|
], order='id DESC', limit=1)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(token.token, response_data['access_token'])
|
|
self.assertEqual(token.token_type, response_data['token_type'])
|
|
self.assertEqual(token.refresh_token, response_data['refresh_token'])
|
|
self.assertEqual(token.scope_ids, self.client.scope_ids[0])
|
|
self.assertEqual(token.user_id, self.user)
|
|
|
|
def test_token_with_right_non_basic_authorization(self):
|
|
""" Check client authentication with a non-Basic Authorization header
|
|
|
|
Must return an invalid_client error : Non basic authorization headers
|
|
are ignored
|
|
"""
|
|
# Define a secret for the client
|
|
self.client.secret = 'OAuth Client secret'
|
|
auth_string = base64.b64encode(
|
|
'{client.identifier}:{client.secret}'.format(client=self.client))
|
|
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
}, headers=[(
|
|
'Authorization',
|
|
'Digest {auth_string}'.format(auth_string=auth_string)),
|
|
])
|
|
self.assertEqual(response.status_code, 401)
|
|
self.assertEqual(
|
|
json.loads(response.data), {'error': 'invalid_client'})
|
|
|
|
def test_successful_token_retrieval(self):
|
|
""" Check the full process for a LegacyApplication
|
|
|
|
GET, then POST, token and informations retrieval
|
|
"""
|
|
# Ask a token to the server
|
|
response = self.post_request('/oauth2/token', data={
|
|
'client_id': self.client.identifier,
|
|
'scope': self.client.scope_ids[0].code,
|
|
'grant_type': self.client.grant_type,
|
|
'username': self.user.login,
|
|
'password': 'demo',
|
|
})
|
|
response_data = json.loads(response.data)
|
|
# A new token should have been generated
|
|
# We can safely pick the latest generated token here, because no other
|
|
# token could have been generated during the test
|
|
token = self.env['oauth.provider.token'].search([
|
|
('client_id', '=', self.client.id),
|
|
], order='id DESC', limit=1)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(token.token, response_data['access_token'])
|
|
self.assertEqual(token.token_type, response_data['token_type'])
|
|
self.assertEqual(token.refresh_token, response_data['refresh_token'])
|
|
self.assertEqual(token.scope_ids, self.client.scope_ids[0])
|
|
self.assertEqual(token.user_id, self.user)
|