Skip to content

Commit

Permalink
Adding app_url to oauth2_provider applications.
Browse files Browse the repository at this point in the history
  • Loading branch information
tyraziel committed Feb 19, 2025
1 parent 10d5ccc commit 0855b28
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions ansible_base/oauth2_provider/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Migration(migrations.Migration):
('algorithm', models.CharField(blank=True, choices=[('', 'No OIDC support'), ('RS256', 'RSA with SHA-2 256'), ('HS256', 'HMAC with SHA-2 256')], default='', max_length=5)),
('post_logout_redirect_uris', models.TextField(blank=True, help_text='Allowed Post Logout URIs list, space separated')),
('redirect_uris', models.TextField(blank=True, help_text='Allowed URIs list, space separated')),
('app_url', models.URLField(blank=True, default=None, null=True, help_text='The URL of the application.')),
('updated', models.DateTimeField(auto_now=True)),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s', to=settings.AUTH_USER_MODEL)),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-18 22:33

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dab_oauth2_provider', '0007_alter_oauth2accesstoken_application_and_more'),
]

operations = [
migrations.AlterField(
model_name='oauth2application',
name='app_url',
field=models.URLField(blank=True, default=None, help_text='The URL of this application.', null=True),
),
]
7 changes: 7 additions & 0 deletions ansible_base/oauth2_provider/models/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ class Meta(oauth2_models.AbstractAccessToken.Meta):
null=True,
)

app_url = models.URLField(
default=None,
blank=True,
null=True,
help_text=_("The URL of this application."),
)

# It would be nice to just use our usual encrypted_fields flow here
# until DOT makes a release with https://github.com/jazzband/django-oauth-toolkit/pull/1311
# there is no way to disable its expectation of using its own hashing
Expand Down
1 change: 1 addition & 0 deletions ansible_base/oauth2_provider/serializers/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Meta:
'client_secret': {'label': _('Client Secret')},
'client_type': {'label': _('Client Type')},
'redirect_uris': {'label': _('Redirect URIs')},
'app_url': {'label': _('Application URL')},
'skip_authorization': {'label': _('Skip Authorization')},
}

Expand Down
102 changes: 102 additions & 0 deletions test_app/tests/oauth2_provider/views/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def test_oauth2_provider_application_create(request, client_fixture, expected_st
'description': 'Test Description',
'organization': organization.pk,
'redirect_uris': 'https://example.com/callback',
'app_url': 'https://example.com',
'authorization_grant_type': 'authorization-code',
'client_type': 'confidential',
},
Expand All @@ -120,11 +121,73 @@ def test_oauth2_provider_application_create(request, client_fixture, expected_st
assert created_app.name == name
assert not created_app.skip_authorization
assert created_app.redirect_uris == 'https://example.com/callback'
assert created_app.app_url == 'https://example.com'
assert created_app.client_type == 'confidential'
assert created_app.authorization_grant_type == 'authorization-code'
assert created_app.organization == organization


@pytest.mark.parametrize(
"client_fixture,expected_status",
[
("admin_api_client", 201),
pytest.param("user_api_client", 201, marks=pytest.mark.xfail(reason="https://github.com/ansible/django-ansible-base/issues/424")),
("unauthenticated_api_client", 401),
],
)
def test_oauth2_provider_application_create_no_app_url(request, client_fixture, expected_status, randname, organization):
"""
As an admin, I should be able to create an OAuth2 application.
"""
client = request.getfixturevalue(client_fixture)
url = get_relative_url("application-list")
name = randname("Test Application")
response = client.post(
url,
data={
'name': name,
'description': 'Test Description',
'organization': organization.pk,
'redirect_uris': 'https://example.com/callback',
'authorization_grant_type': 'authorization-code',
'client_type': 'confidential',
},
)
assert response.status_code == expected_status, response.data
if expected_status == 201:
assert response.data['name'] == name
assert OAuth2Application.objects.get(pk=response.data['id']).organization == organization

created_app = OAuth2Application.objects.get(client_id=response.data['client_id'])
assert created_app.name == name
assert not created_app.skip_authorization
assert created_app.redirect_uris == 'https://example.com/callback'
assert created_app.app_url is None or created_app.app_url == ''
assert created_app.client_type == 'confidential'
assert created_app.authorization_grant_type == 'authorization-code'
assert created_app.organization == organization


def test_oauth2_provider_application_create_malformed_app_url(admin_api_client):
"""
Validate malformed URL for app_url throws a 400
"""
url = get_relative_url("application-list")
response = admin_api_client.post(
url,
data={
'name': 'Throw me a 400',
'description': 'Test Description',
'organization': '1',
'redirect_uris': 'https://example.com/callback',
'app_url': 'make this throw a 400',
'authorization_grant_type': 'authorization-code',
'client_type': 'confidential',
},
)
assert response.status_code == 400


def test_oauth2_provider_application_validator(admin_api_client):
"""
If we don't get enough information in the request, we should 400
Expand Down Expand Up @@ -163,6 +226,7 @@ def test_oauth2_provider_application_update(request, client_fixture, expected_st
'name': 'Updated Name',
'description': 'Updated Description',
'redirect_uris': 'http://example.com/updated',
'app_url': 'http://example.com/app_url_updated',
'client_type': 'public',
},
)
Expand All @@ -176,9 +240,45 @@ def test_oauth2_provider_application_update(request, client_fixture, expected_st
assert oauth2_application.name == 'Updated Name'
assert oauth2_application.description == 'Updated Description'
assert oauth2_application.redirect_uris == 'http://example.com/updated'
assert oauth2_application.app_url == 'http://example.com/app_url_updated'
assert oauth2_application.client_type == 'public'


@pytest.mark.parametrize(
"client_fixture,expected_status",
[
("admin_api_client", 200),
pytest.param("user_api_client", 200, marks=pytest.mark.xfail(reason="https://github.com/ansible/django-ansible-base/issues/424")),
("unauthenticated_api_client", 401),
],
)
@pytest.mark.django_db
def test_oauth2_provider_application_update_to_blank_app_url(request, client_fixture, expected_status, oauth2_application):
"""
Test that we can update oauth2 applications iff we are authenticated.
"""
oauth2_application = oauth2_application[0]
client = request.getfixturevalue(client_fixture)
url = get_relative_url("application-detail", args=[oauth2_application.pk])
response = client.patch(
url,
data={
'name': 'Updated Name for Blank app_url',
'description': 'Updated Description - blank app_url',
'app_url': '',
},
)
assert response.status_code == expected_status, response.data
if expected_status == 200:
assert response.data['name'] == 'Updated Name for Blank app_url'
assert response.data['description'] == 'Updated Description - blank app_url'
assert response.data['app_url'] == ''
oauth2_application.refresh_from_db()
assert oauth2_application.name == 'Updated Name for Blank app_url'
assert oauth2_application.description == 'Updated Description - blank app_url'
assert oauth2_application.app_url == ''


def test_oauth2_provider_application_client_secret_encrypted(admin_api_client, organization):
"""
The client_secret should be encrypted in the database.
Expand All @@ -194,6 +294,7 @@ def test_oauth2_provider_application_client_secret_encrypted(admin_api_client, o
'description': 'Test Description',
'organization': organization.pk,
'redirect_uris': 'https://example.com/callback',
'app_url': 'https://example.com',
'authorization_grant_type': 'authorization-code',
'client_type': 'confidential',
},
Expand Down Expand Up @@ -238,6 +339,7 @@ def test_oauth2_provider_application_client_secret_encrypted(admin_api_client, o
'description': 'Updated Description',
'organization': organization.pk,
'redirect_uris': 'http://example.com/updated',
'app_url': 'http://example.com/update_app_url',
'client_type': 'public',
'authorization_grant_type': 'password',
},
Expand Down

0 comments on commit 0855b28

Please sign in to comment.