mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 08:21:15 +03:00
Merge pull request #3961 from rooftopcellist/rm_implicit
remove implicit grant type for OAuth 2 apps Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
commit
4b1fc7894d
@ -1108,7 +1108,7 @@ class UserAuthorizedTokenSerializer(BaseOAuth2TokenSerializer):
|
||||
)
|
||||
obj = super(UserAuthorizedTokenSerializer, self).create(validated_data)
|
||||
obj.save()
|
||||
if obj.application and obj.application.authorization_grant_type != 'implicit':
|
||||
if obj.application:
|
||||
RefreshToken.objects.create(
|
||||
user=current_user,
|
||||
token=generate_token(),
|
||||
@ -1130,7 +1130,7 @@ class OAuth2TokenSerializer(BaseOAuth2TokenSerializer):
|
||||
if obj.application and obj.application.user:
|
||||
obj.user = obj.application.user
|
||||
obj.save()
|
||||
if obj.application and obj.application.authorization_grant_type != 'implicit':
|
||||
if obj.application:
|
||||
RefreshToken.objects.create(
|
||||
user=current_user,
|
||||
token=generate_token(),
|
||||
|
@ -29,17 +29,6 @@ to the redirect_uri specified in the application. The client application will th
|
||||
AWX will respond with the `access_token`, `token_type`, `refresh_token`, and `expires_in`. For more
|
||||
information on testing this flow, refer to [django-oauth-toolkit](http://django-oauth-toolkit.readthedocs.io/en/latest/tutorial/tutorial_01.html#test-your-authorization-server).
|
||||
|
||||
## Create Token for an Application using Implicit grant type
|
||||
Suppose we have an application "admin's app" of grant type `implicit`.
|
||||
In API browser, first make sure the user is logged in via session auth, then visit authorization
|
||||
endpoint with given parameters:
|
||||
```text
|
||||
http://localhost:8013/api/o/authorize/?response_type=token&client_id=L0uQQWW8pKX51hoqIRQGsuqmIdPi2AcXZ9EJRGmj&scope=read
|
||||
```
|
||||
Here the value of `client_id` should be the same as that of `client_id` field of underlying application.
|
||||
On success, an authorization page should be displayed asking the logged in user to grant/deny the access token.
|
||||
Once the user clicks on 'grant', the API browser will try POSTing to the same endpoint with the same parameters
|
||||
in POST body, on success a 302 redirect will be returned.
|
||||
|
||||
## Create Token for an Application using Password grant type
|
||||
|
||||
|
20
awx/main/migrations/0079_v360_rm_implicit_oauth2_apps.py
Normal file
20
awx/main/migrations/0079_v360_rm_implicit_oauth2_apps.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-05-28 17:15
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0078_v360_clear_sessions_tokens_jt'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='oauth2application',
|
||||
name='authorization_grant_type',
|
||||
field=models.CharField(choices=[('authorization-code', 'Authorization code'), ('password', 'Resource owner password-based')], help_text='The Grant type the user must use for acquire tokens for this application.', max_length=32),
|
||||
),
|
||||
]
|
@ -38,11 +38,9 @@ class OAuth2Application(AbstractApplication):
|
||||
)
|
||||
|
||||
GRANT_AUTHORIZATION_CODE = "authorization-code"
|
||||
GRANT_IMPLICIT = "implicit"
|
||||
GRANT_PASSWORD = "password"
|
||||
GRANT_TYPES = (
|
||||
(GRANT_AUTHORIZATION_CODE, _("Authorization code")),
|
||||
(GRANT_IMPLICIT, _("Implicit")),
|
||||
(GRANT_PASSWORD, _("Resource owner password-based")),
|
||||
)
|
||||
|
||||
|
@ -4,7 +4,6 @@ import json
|
||||
|
||||
from django.db import connection
|
||||
from django.test.utils import override_settings
|
||||
from django.test import Client
|
||||
from django.utils.encoding import smart_str, smart_bytes
|
||||
|
||||
from awx.main.utils.encryption import decrypt_value, get_encryption_key
|
||||
@ -114,7 +113,7 @@ def test_oauth_application_update(oauth_application, organization, patch, admin,
|
||||
'name': 'Test app with immutable grant type and user',
|
||||
'organization': organization.pk,
|
||||
'redirect_uris': 'http://localhost/api/',
|
||||
'authorization_grant_type': 'implicit',
|
||||
'authorization_grant_type': 'password',
|
||||
'skip_authorization': True,
|
||||
}, admin, expect=200
|
||||
)
|
||||
@ -175,27 +174,22 @@ def test_oauth_token_create(oauth_application, get, post, admin):
|
||||
assert response.data['summary_fields']['tokens']['results'][0] == {
|
||||
'id': token.pk, 'scope': token.scope, 'token': '************'
|
||||
}
|
||||
# If the application is implicit grant type, no new refresb tokens should be created.
|
||||
# The following tests check for that.
|
||||
oauth_application.authorization_grant_type = 'implicit'
|
||||
oauth_application.save()
|
||||
token_count = RefreshToken.objects.count()
|
||||
|
||||
response = post(
|
||||
reverse('api:o_auth2_token_list'),
|
||||
{'scope': 'read', 'application': oauth_application.pk}, admin, expect=201
|
||||
)
|
||||
assert response.data['refresh_token'] is None
|
||||
assert response.data['refresh_token']
|
||||
response = post(
|
||||
reverse('api:user_authorized_token_list', kwargs={'pk': admin.pk}),
|
||||
{'scope': 'read', 'application': oauth_application.pk}, admin, expect=201
|
||||
)
|
||||
assert response.data['refresh_token'] is None
|
||||
assert response.data['refresh_token']
|
||||
response = post(
|
||||
reverse('api:application_o_auth2_token_list', kwargs={'pk': oauth_application.pk}),
|
||||
{'scope': 'read'}, admin, expect=201
|
||||
)
|
||||
assert response.data['refresh_token'] is None
|
||||
assert token_count == RefreshToken.objects.count()
|
||||
assert response.data['refresh_token']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@ -260,30 +254,6 @@ def test_oauth_list_user_tokens(oauth_application, post, get, admin, alice):
|
||||
post(url, {'scope': 'read'}, user, expect=201)
|
||||
response = get(url, admin, expect=200)
|
||||
assert response.data['count'] == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_implicit_authorization(oauth_application, admin):
|
||||
oauth_application.client_type = 'confidential'
|
||||
oauth_application.authorization_grant_type = 'implicit'
|
||||
oauth_application.redirect_uris = 'http://test.com'
|
||||
oauth_application.save()
|
||||
data = {
|
||||
'response_type': 'token',
|
||||
'client_id': oauth_application.client_id,
|
||||
'client_secret': oauth_application.client_secret,
|
||||
'scope': 'read',
|
||||
'redirect_uri': 'http://test.com',
|
||||
'allow': True
|
||||
}
|
||||
|
||||
request_client = Client()
|
||||
request_client.force_login(admin, 'django.contrib.auth.backends.ModelBackend')
|
||||
refresh_token_count = RefreshToken.objects.count()
|
||||
response = request_client.post(drf_reverse('api:authorize'), data)
|
||||
assert 'http://test.com' in response.url and 'access_token' in response.url
|
||||
# Make sure no refresh token is created for app with implicit grant type.
|
||||
assert refresh_token_count == RefreshToken.objects.count()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
@ -22,7 +22,6 @@ const addEditElements = {
|
||||
|
||||
const authorizationGrantTypeOptions = {
|
||||
authorizationCode: 'Authorization code',
|
||||
implicit: 'Implicit',
|
||||
resourceOwnerPasswordBased: 'Resource owner password-based',
|
||||
};
|
||||
|
||||
|
@ -235,7 +235,7 @@ This page lists OAuth 2 utility endpoints used for authorization, token refresh
|
||||
Note endpoints other than `/api/o/authorize/` are not meant to be used in browsers and do not
|
||||
support HTTP GET. The endpoints here strictly follow
|
||||
[RFC specs for OAuth 2](https://tools.ietf.org/html/rfc6749), so please use that for detailed
|
||||
reference. The `implicit` grant type can only be used to acquire a access token if the user is already logged in via session authentication, as that confirms that the user is authorized to create an access token. Here we give some examples to demonstrate the typical usage of these endpoints in
|
||||
reference. Here we give some examples to demonstrate the typical usage of these endpoints in
|
||||
AWX context (Note AWX net location default to `http://localhost:8013` in examples):
|
||||
|
||||
|
||||
@ -265,51 +265,6 @@ AWX will respond with the `access_token`, `token_type`, `refresh_token`, and `ex
|
||||
information on testing this flow, refer to [django-oauth-toolkit](http://django-oauth-toolkit.readthedocs.io/en/latest/tutorial/tutorial_01.html#test-your-authorization-server).
|
||||
|
||||
|
||||
|
||||
#### Application using `implicit` grant type
|
||||
The use case: single page web apps that can't keep a client_secret as secure. This method with skips the
|
||||
authorization code part of the flow and just returns an access token.
|
||||
Suppose we have an application `admin's app` of grant type `implicit`:
|
||||
```text
|
||||
{
|
||||
"id": 1,
|
||||
"type": "application",
|
||||
"related": {
|
||||
...
|
||||
"name": "admin's app",
|
||||
"user": 1,
|
||||
"client_id": "L0uQQWW8pKX51hoqIRQGsuqmIdPi2AcXZ9EJRGmj",
|
||||
"client_secret": "9Wp4dUrUsigI8J15fQYJ3jn0MJHLkAjyw7ikBsABeWTNJbZwy7eB2Xro9ykYuuygerTPQ2gIF2DCTtN3kurkt0Me3AhanEw6peRNvNLs1NNfI4f53mhX8zo5JQX0BKy5",
|
||||
"client_type": "confidential",
|
||||
"redirect_uris": "http://<awx>/api/",
|
||||
"authorization_grant_type": "implicit",
|
||||
"skip_authorization": false
|
||||
}
|
||||
```
|
||||
|
||||
In API browser, first make sure the user is logged in via session auth, then visit authorization
|
||||
endpoint with given parameters:
|
||||
```text
|
||||
http://localhost:8013/api/o/authorize/?response_type=token&client_id=L0uQQWW8pKX51hoqIRQGsuqmIdPi2AcXZ9EJRGmj&scope=read
|
||||
```
|
||||
Here the value of `client_id` should be the same as that of `client_id` field of underlying application.
|
||||
On success, an authorization page should be displayed asking the logged in user to grant/deny the access token.
|
||||
Once the user clicks on 'grant', the API browser will try POSTing to the same endpoint with the same parameters in POST body, on success a 302 redirect will be returned:
|
||||
```text
|
||||
HTTP/1.1 302 Found
|
||||
Connection:keep-alive
|
||||
Content-Language:en
|
||||
Content-Length:0
|
||||
Content-Type:text/html; charset=utf-8
|
||||
Date:Tue, 05 Dec 2017 20:36:19 GMT
|
||||
Location:http://localhost:8013/api/#access_token=0lVJJkolFTwYawHyGkk7NTmSKdzBen&token_type=Bearer&state=&expires_in=315360000000&scope=read
|
||||
Server:nginx/1.12.2
|
||||
Strict-Transport-Security:max-age=15768000
|
||||
Vary:Accept-Language, Cookie
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Application using `password` grant type
|
||||
This is also called the `resource owner credentials grant`. This is for use by users who have
|
||||
native access to the web app. This should be used when the client is the Resource owner. Suppose
|
||||
|
Loading…
Reference in New Issue
Block a user