1
0
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:
softwarefactory-project-zuul[bot] 2019-05-29 20:27:11 +00:00 committed by GitHub
commit 4b1fc7894d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 28 additions and 97 deletions

View File

@ -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(),

View File

@ -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

View 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),
),
]

View File

@ -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")),
)

View File

@ -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
@ -262,30 +256,6 @@ def test_oauth_list_user_tokens(oauth_application, post, get, admin, alice):
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
def test_refresh_accesstoken(oauth_application, post, get, delete, admin):
response = post(

View File

@ -22,7 +22,6 @@ const addEditElements = {
const authorizationGrantTypeOptions = {
authorizationCode: 'Authorization code',
implicit: 'Implicit',
resourceOwnerPasswordBased: 'Resource owner password-based',
};

View File

@ -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