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

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016 SYLEAM
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. import base64
  5. import json
  6. import logging
  7. from .common_test_controller import OAuthProviderControllerTransactionCase
  8. from .common_test_oauth_provider_controller import \
  9. TestOAuthProviderRefreshTokenController, \
  10. TestOAuthProviderTokeninfoController, \
  11. TestOAuthProviderUserinfoController, \
  12. TestOAuthProviderOtherinfoController, \
  13. TestOAuthProviderRevokeTokenController
  14. _logger = logging.getLogger(__name__)
  15. class TestOAuthProviderController(
  16. OAuthProviderControllerTransactionCase,
  17. TestOAuthProviderRefreshTokenController,
  18. TestOAuthProviderTokeninfoController,
  19. TestOAuthProviderUserinfoController,
  20. TestOAuthProviderOtherinfoController,
  21. TestOAuthProviderRevokeTokenController):
  22. def setUp(self):
  23. super(TestOAuthProviderController, self).setUp('legacy application')
  24. def test_token_error_missing_arguments(self):
  25. """ Check /oauth2/token without any argument
  26. Must return an unsupported_grant_type error
  27. """
  28. response = self.post_request('/oauth2/token')
  29. self.assertEqual(response.status_code, 401)
  30. self.assertEqual(
  31. json.loads(response.data), {'error': 'invalid_client_id'})
  32. def test_token_error_wrong_grant_type(self):
  33. """ Check /oauth2/token with an invalid grant type
  34. Must return an unsupported_grant_type error
  35. """
  36. response = self.post_request('/oauth2/token', data={
  37. 'client_id': self.client.identifier,
  38. 'grant_type': 'Wrong grant type',
  39. 'username': 'Wrong username',
  40. 'password': 'Wrong password',
  41. })
  42. self.assertEqual(response.status_code, 400)
  43. self.assertEqual(
  44. json.loads(response.data), {'error': 'unsupported_grant_type'})
  45. def test_token_error_missing_username(self):
  46. """ Check /oauth2/token without username
  47. Must return an invalid_request error
  48. """
  49. response = self.post_request('/oauth2/token', data={
  50. 'client_id': self.client.identifier,
  51. 'grant_type': self.client.grant_type,
  52. })
  53. self.assertEqual(response.status_code, 400)
  54. self.assertEqual(json.loads(response.data), {
  55. 'error': 'invalid_request',
  56. 'error_description': 'Request is missing username parameter.',
  57. })
  58. def test_token_error_missing_password(self):
  59. """ Check /oauth2/token without password
  60. Must return an invalid_request error
  61. """
  62. response = self.post_request('/oauth2/token', data={
  63. 'client_id': self.client.identifier,
  64. 'grant_type': self.client.grant_type,
  65. 'username': 'Wrong username',
  66. })
  67. self.assertEqual(response.status_code, 400)
  68. self.assertEqual(json.loads(response.data), {
  69. 'error': 'invalid_request',
  70. 'error_description': 'Request is missing password parameter.',
  71. })
  72. def test_token_error_missing_client_id(self):
  73. """ Check /oauth2/token without client
  74. Must return an unauthorized_client error
  75. """
  76. response = self.post_request('/oauth2/token', data={
  77. 'grant_type': self.client.grant_type,
  78. })
  79. self.assertEqual(response.status_code, 401)
  80. self.assertEqual(
  81. json.loads(response.data), {'error': 'invalid_client_id'})
  82. def test_token_error_wrong_client_identifier(self):
  83. """ Check /oauth2/token with a wrong client identifier
  84. Must return an invalid_client_id error
  85. """
  86. response = self.post_request('/oauth2/token', data={
  87. 'grant_type': self.client.grant_type,
  88. 'client_id': 'Wrong client identifier',
  89. })
  90. self.assertEqual(response.status_code, 401)
  91. self.assertEqual(
  92. json.loads(response.data), {'error': 'invalid_client_id'})
  93. def test_token_error_wrong_username(self):
  94. """ Check /oauth2/token with a wrong username
  95. Must return an invalid_grant error
  96. """
  97. response = self.post_request('/oauth2/token', data={
  98. 'grant_type': self.client.grant_type,
  99. 'client_id': self.client.identifier,
  100. 'username': 'Wrong username',
  101. 'password': 'demo',
  102. })
  103. self.assertEqual(response.status_code, 401)
  104. self.assertEqual(json.loads(response.data), {
  105. 'error': 'invalid_grant',
  106. 'error_description': 'Invalid credentials given.',
  107. })
  108. def test_token_error_wrong_password(self):
  109. """ Check /oauth2/token with a wrong password
  110. Must return an invalid_grant error
  111. """
  112. response = self.post_request('/oauth2/token', data={
  113. 'grant_type': self.client.grant_type,
  114. 'client_id': self.client.identifier,
  115. 'username': self.user.login,
  116. 'password': 'Wrong password',
  117. })
  118. self.assertEqual(response.status_code, 401)
  119. self.assertEqual(json.loads(response.data), {
  120. 'error': 'invalid_grant',
  121. 'error_description': 'Invalid credentials given.',
  122. })
  123. def test_token_error_wrong_client_id(self):
  124. """ Check /oauth2/token with a wrong client id
  125. Must return an invalid_client_id error
  126. """
  127. response = self.post_request('/oauth2/token', data={
  128. 'grant_type': self.client.grant_type,
  129. 'client_id': 'Wrong client id',
  130. 'scope': self.client.scope_ids[0].code,
  131. })
  132. self.assertEqual(response.status_code, 401)
  133. self.assertEqual(
  134. json.loads(response.data), {'error': 'invalid_client_id'})
  135. def test_token_error_missing_refresh_token(self):
  136. """ Check /oauth2/token in refresh token mode without refresh token
  137. Must return an invalid_request error
  138. """
  139. response = self.post_request('/oauth2/token', data={
  140. 'grant_type': 'refresh_token',
  141. 'client_id': self.client.identifier,
  142. 'scope': self.client.scope_ids[0].code,
  143. })
  144. self.assertEqual(response.status_code, 400)
  145. self.assertEqual(json.loads(response.data), {
  146. 'error': 'invalid_request',
  147. 'error_description': 'Missing refresh token parameter.',
  148. })
  149. def test_token_error_invalid_refresh_token(self):
  150. """ Check /oauth2/token in refresh token mode with an invalid refresh token
  151. Must return an invalid_grant error
  152. """
  153. response = self.post_request('/oauth2/token', data={
  154. 'grant_type': 'refresh_token',
  155. 'client_id': self.client.identifier,
  156. 'scope': self.client.scope_ids[0].code,
  157. 'refresh_token': 'Wrong refresh token',
  158. })
  159. self.assertEqual(response.status_code, 401)
  160. self.assertEqual(json.loads(response.data), {'error': 'invalid_grant'})
  161. def test_token_with_missing_secret(self):
  162. """ Check client authentication without the secret provided
  163. Must return an invalid_client error
  164. """
  165. # Define a secret for the client
  166. self.client.secret = 'OAuth Client secret'
  167. # Ask a token to the server
  168. response = self.post_request('/oauth2/token', data={
  169. 'client_id': self.client.identifier,
  170. 'scope': self.client.scope_ids[0].code,
  171. 'grant_type': self.client.grant_type,
  172. 'username': self.user.login,
  173. 'password': 'demo',
  174. })
  175. self.assertEqual(response.status_code, 401)
  176. self.assertEqual(
  177. json.loads(response.data), {'error': 'invalid_client'})
  178. def test_token_with_unexpected_secret(self):
  179. """ Check client authentication with an unexpected secret provided
  180. Must return an invalid_client error
  181. """
  182. # Don't define a secret for the client
  183. auth_string = base64.b64encode(
  184. '{client.identifier}:secret'.format(client=self.client))
  185. # Ask a token to the server
  186. response = self.post_request('/oauth2/token', data={
  187. 'client_id': self.client.identifier,
  188. 'scope': self.client.scope_ids[0].code,
  189. 'grant_type': self.client.grant_type,
  190. 'username': self.user.login,
  191. 'password': 'demo',
  192. }, headers=[(
  193. 'Authorization',
  194. 'Basic {auth_string}'.format(auth_string=auth_string)),
  195. ])
  196. self.assertEqual(response.status_code, 401)
  197. self.assertEqual(
  198. json.loads(response.data), {'error': 'invalid_client'})
  199. def test_token_with_wrong_secret(self):
  200. """ Check client authentication with a wrong secret
  201. Must return an invalid_client error
  202. """
  203. # Define a secret for the client
  204. self.client.secret = 'OAuth Client secret'
  205. auth_string = base64.b64encode(
  206. '{client.identifier}:secret'.format(client=self.client))
  207. # Ask a token to the server
  208. response = self.post_request('/oauth2/token', data={
  209. 'client_id': self.client.identifier,
  210. 'scope': self.client.scope_ids[0].code,
  211. 'grant_type': self.client.grant_type,
  212. 'username': self.user.login,
  213. 'password': 'demo',
  214. }, headers=[(
  215. 'Authorization',
  216. 'Basic {auth_string}'.format(auth_string=auth_string)),
  217. ])
  218. self.assertEqual(response.status_code, 401)
  219. self.assertEqual(
  220. json.loads(response.data), {'error': 'invalid_client'})
  221. def test_token_with_secret(self):
  222. """ Check client authentication from Authorization header """
  223. # Define a secret for the client
  224. self.client.secret = 'OAuth Client secret'
  225. auth_string = base64.b64encode(
  226. '{client.identifier}:{client.secret}'.format(client=self.client))
  227. # Ask a token to the server
  228. response = self.post_request('/oauth2/token', data={
  229. 'client_id': self.client.identifier,
  230. 'scope': self.client.scope_ids[0].code,
  231. 'grant_type': self.client.grant_type,
  232. 'username': self.user.login,
  233. 'password': 'demo',
  234. }, headers=[(
  235. 'Authorization',
  236. 'Basic {auth_string}'.format(auth_string=auth_string)),
  237. ])
  238. response_data = json.loads(response.data)
  239. # A new token should have been generated
  240. # We can safely pick the latest generated token here, because no other
  241. # token could have been generated during the test
  242. token = self.env['oauth.provider.token'].search([
  243. ('client_id', '=', self.client.id),
  244. ], order='id DESC', limit=1)
  245. self.assertEqual(response.status_code, 200)
  246. self.assertEqual(token.token, response_data['access_token'])
  247. self.assertEqual(token.token_type, response_data['token_type'])
  248. self.assertEqual(token.refresh_token, response_data['refresh_token'])
  249. self.assertEqual(token.scope_ids, self.client.scope_ids[0])
  250. self.assertEqual(token.user_id, self.user)
  251. def test_token_with_wrong_non_basic_authorization(self):
  252. """ Check client authentication with a non-Basic Authorization header
  253. Must generate a token : Non basic authorization headers are ignored
  254. """
  255. # Don't define a secret for the client
  256. auth_string = base64.b64encode(
  257. '{client.identifier}:secret'.format(client=self.client))
  258. # Ask a token to the server
  259. response = self.post_request('/oauth2/token', data={
  260. 'client_id': self.client.identifier,
  261. 'scope': self.client.scope_ids[0].code,
  262. 'grant_type': self.client.grant_type,
  263. 'username': self.user.login,
  264. 'password': 'demo',
  265. }, headers=[(
  266. 'Authorization',
  267. 'Digest {auth_string}'.format(auth_string=auth_string)),
  268. ])
  269. response_data = json.loads(response.data)
  270. # A new token should have been generated
  271. # We can safely pick the latest generated token here, because no other
  272. # token could have been generated during the test
  273. token = self.env['oauth.provider.token'].search([
  274. ('client_id', '=', self.client.id),
  275. ], order='id DESC', limit=1)
  276. self.assertEqual(response.status_code, 200)
  277. self.assertEqual(token.token, response_data['access_token'])
  278. self.assertEqual(token.token_type, response_data['token_type'])
  279. self.assertEqual(token.refresh_token, response_data['refresh_token'])
  280. self.assertEqual(token.scope_ids, self.client.scope_ids[0])
  281. self.assertEqual(token.user_id, self.user)
  282. def test_token_with_right_non_basic_authorization(self):
  283. """ Check client authentication with a non-Basic Authorization header
  284. Must return an invalid_client error : Non basic authorization headers
  285. are ignored
  286. """
  287. # Define a secret for the client
  288. self.client.secret = 'OAuth Client secret'
  289. auth_string = base64.b64encode(
  290. '{client.identifier}:{client.secret}'.format(client=self.client))
  291. # Ask a token to the server
  292. response = self.post_request('/oauth2/token', data={
  293. 'client_id': self.client.identifier,
  294. 'scope': self.client.scope_ids[0].code,
  295. 'grant_type': self.client.grant_type,
  296. 'username': self.user.login,
  297. 'password': 'demo',
  298. }, headers=[(
  299. 'Authorization',
  300. 'Digest {auth_string}'.format(auth_string=auth_string)),
  301. ])
  302. self.assertEqual(response.status_code, 401)
  303. self.assertEqual(
  304. json.loads(response.data), {'error': 'invalid_client'})
  305. def test_successful_token_retrieval(self):
  306. """ Check the full process for a LegacyApplication
  307. GET, then POST, token and informations retrieval
  308. """
  309. # Ask a token to the server
  310. response = self.post_request('/oauth2/token', data={
  311. 'client_id': self.client.identifier,
  312. 'scope': self.client.scope_ids[0].code,
  313. 'grant_type': self.client.grant_type,
  314. 'username': self.user.login,
  315. 'password': 'demo',
  316. })
  317. response_data = json.loads(response.data)
  318. # A new token should have been generated
  319. # We can safely pick the latest generated token here, because no other
  320. # token could have been generated during the test
  321. token = self.env['oauth.provider.token'].search([
  322. ('client_id', '=', self.client.id),
  323. ], order='id DESC', limit=1)
  324. self.assertEqual(response.status_code, 200)
  325. self.assertEqual(token.token, response_data['access_token'])
  326. self.assertEqual(token.token_type, response_data['token_type'])
  327. self.assertEqual(token.refresh_token, response_data['refresh_token'])
  328. self.assertEqual(token.scope_ids, self.client.scope_ids[0])
  329. self.assertEqual(token.user_id, self.user)