Skip to content

Commit dec5e2f

Browse files
emmanuelangelo4199dopry
authored andcommitted
Add dynamic help text for client_secret field on application form
Fixes #1635 - warns users to save their secret on creation, and informs them it is hashed and unrecoverable when editing.
1 parent 1fbc081 commit dec5e2f

3 files changed

Lines changed: 45 additions & 36 deletions

File tree

oauth2_provider/forms.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from django import forms
2+
from django.forms.models import modelform_factory
3+
from .models import get_application_model
24

35

46
class AllowForm(forms.Form):
@@ -26,3 +28,18 @@ class ConfirmLogoutForm(forms.Form):
2628
def __init__(self, *args, **kwargs):
2729
self.request = kwargs.pop("request", None)
2830
super(ConfirmLogoutForm, self).__init__(*args, **kwargs)
31+
32+
33+
class ApplicationForm(forms.ModelForm):
34+
def __init__(self, *args, **kwargs):
35+
super().__init__(*args, **kwargs)
36+
if self.instance and self.instance.pk:
37+
self.fields["client_secret"].help_text = (
38+
"⚠️ The client secret has been hashed and can no longer be viewed. "
39+
"If you need the original value, you must regenerate it and save it immediately."
40+
)
41+
else:
42+
self.fields["client_secret"].help_text = (
43+
"⚠️ Copy and store this secret now. "
44+
"Once saved, it will be hashed and cannot be recovered."
45+
)

oauth2_provider/views/application.py

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@
33
from django.urls import reverse_lazy
44
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView
55

6+
from ..forms import ApplicationForm
67
from ..models import get_application_model
78

9+
APPLICATION_FIELDS = (
10+
"name",
11+
"client_id",
12+
"client_secret",
13+
"hash_client_secret",
14+
"client_type",
15+
"authorization_grant_type",
16+
"redirect_uris",
17+
"post_logout_redirect_uris",
18+
"allowed_origins",
19+
"algorithm",
20+
)
21+
822

923
class ApplicationOwnerIsUserMixin(LoginRequiredMixin):
1024
"""
@@ -25,24 +39,7 @@ class ApplicationRegistration(LoginRequiredMixin, CreateView):
2539
template_name = "oauth2_provider/application_registration_form.html"
2640

2741
def get_form_class(self):
28-
"""
29-
Returns the form class for the application model
30-
"""
31-
return modelform_factory(
32-
get_application_model(),
33-
fields=(
34-
"name",
35-
"client_id",
36-
"client_secret",
37-
"hash_client_secret",
38-
"client_type",
39-
"authorization_grant_type",
40-
"redirect_uris",
41-
"post_logout_redirect_uris",
42-
"allowed_origins",
43-
"algorithm",
44-
),
45-
)
42+
return modelform_factory(get_application_model(), form=ApplicationForm, fields=APPLICATION_FIELDS)
4643

4744
def form_valid(self, form):
4845
form.instance.user = self.request.user
@@ -86,21 +83,4 @@ class ApplicationUpdate(ApplicationOwnerIsUserMixin, UpdateView):
8683
template_name = "oauth2_provider/application_form.html"
8784

8885
def get_form_class(self):
89-
"""
90-
Returns the form class for the application model
91-
"""
92-
return modelform_factory(
93-
get_application_model(),
94-
fields=(
95-
"name",
96-
"client_id",
97-
"client_secret",
98-
"hash_client_secret",
99-
"client_type",
100-
"authorization_grant_type",
101-
"redirect_uris",
102-
"post_logout_redirect_uris",
103-
"allowed_origins",
104-
"algorithm",
105-
),
106-
)
86+
return modelform_factory(get_application_model(), form=ApplicationForm, fields=APPLICATION_FIELDS)

tests/test_application_views.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,15 @@ def test_application_update(self):
281281
self.assertEqual(self.app_foo_1.post_logout_redirect_uris, form_data["post_logout_redirect_uris"])
282282
self.assertEqual(self.app_foo_1.client_type, form_data["client_type"])
283283
self.assertEqual(self.app_foo_1.authorization_grant_type, form_data["authorization_grant_type"])
284+
285+
def test_client_secret_help_text_new_application(self):
286+
self.client.login(username="foo_user", password="123456")
287+
response = self.client.get(reverse("oauth2_provider:register"))
288+
form = response.context["form"]
289+
self.assertIn("Copy and store this secret now", form.fields["client_secret"].help_text)
290+
291+
def test_client_secret_help_text_existing_application(self):
292+
self.client.login(username="foo_user", password="123456")
293+
response = self.client.get(reverse("oauth2_provider:update", args=(self.app_foo_1.pk,)))
294+
form = response.context["form"]
295+
self.assertIn("has been hashed", form.fields["client_secret"].help_text)

0 commit comments

Comments
 (0)