Skip to content

Commit f65b59a

Browse files
committed
Use Django's messages framework to only show the client secret once
1 parent fd64f0e commit f65b59a

File tree

4 files changed

+34
-24
lines changed

4 files changed

+34
-24
lines changed

docs/getting_started.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ Start the development server::
245245

246246
Point your browser to http://127.0.0.1:8000/o/applications/register/ lets create an application.
247247

248-
Fill the form as show in the screenshot below and before save take note of ``Client id`` and ``Client secret``, we will use it in a minute.
248+
Fill the form as show in the screenshot below and after saving take note of the ``client secret`` (possibly shown in the flash message) and the ``client ID``, we will use them both in a minute.
249249

250-
If you want to use this application with OIDC and ``HS256`` (see :doc:`OpenID Connect <oidc>`), uncheck ``Hash client secret`` to allow verifying tokens using JWT signatures. This means your client secret will be stored in cleartext but is the only way to successfully use signed JWT's with ``HS256``.
250+
If you want to use this application with OIDC and ``HS256`` (see :doc:`OpenID Connect <oidc>`), uncheck ``Hash client secret`` to allow verifying tokens using JWT signatures. Unchecking that means your client secret will be stored on the server in cleartext but is the only way to successfully use signed JWT's with ``HS256``.
251251

252252
.. note::
253253
``RS256`` is the more secure algorithm for signing your JWTs. Only use ``HS256`` if you must.

docs/install.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Install with pip::
55

66
pip install django-oauth-toolkit
77

8-
Add ``oauth2_provider`` to your ``INSTALLED_APPS``
8+
Enable and configure Django's messages framework, and add ``oauth2_provider`` to your ``INSTALLED_APPS``
99

1010
.. code-block:: python
1111

oauth2_provider/templates/oauth2_provider/application_detail.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
<div class="block-center">
66
<h3 class="block-center-heading">{{ application.name }}</h3>
77

8+
{% if messages %}
9+
<ul class="messages">
10+
{% for message in messages %}
11+
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
12+
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
13+
{{ message }}
14+
</li>
15+
{% endfor %}
16+
</ul>
17+
{% endif %}
18+
819
<ul class="unstyled">
920
<li>
1021
<p><b>{% trans "Client ID" %}</b></p>
@@ -15,9 +26,6 @@ <h3 class="block-center-heading">{{ application.name }}</h3>
1526
<li>
1627
<p><b>{% trans "Client secret" %}</b></p>
1728
<p>{{ client_secret }}</p>
18-
{% if show_client_secret_once %}
19-
<p class="error">{% translate "This will only be displayed once - copy it now!" %}</p>
20-
{% endif %}
2129
</li>
2230
{% endif %}
2331

oauth2_provider/views/application.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
from django.contrib import messages
12
from django.contrib.auth.mixins import LoginRequiredMixin
23
from django.forms.models import modelform_factory
34
from django.urls import reverse_lazy
5+
from django.utils.safestring import mark_safe
6+
from django.utils.translation import gettext as _
47
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView
58

69
from ..models import get_application_model
@@ -22,9 +25,7 @@ class ApplicationRegistration(LoginRequiredMixin, CreateView):
2225
View used to register a new Application for the request.user
2326
"""
2427

25-
context_object_name = "application"
2628
template_name = "oauth2_provider/application_registration_form.html"
27-
success_template_name = "oauth2_provider/application_detail.html"
2829

2930
def get_form_class(self):
3031
"""
@@ -46,22 +47,23 @@ def get_form_class(self):
4647

4748
def form_valid(self, form):
4849
form.instance.user = self.request.user
49-
if not form.cleaned_data["hash_client_secret"]:
50-
return super().form_valid(form)
51-
52-
client_secret = form.instance.client_secret
53-
self.object = form.save()
54-
return self.response_class(
55-
request=self.request,
56-
template=self.success_template_name,
57-
context=self.get_context_data(
58-
client_secret=client_secret,
59-
show_client_secret_once=self.object.hash_client_secret,
60-
**{self.context_object_name: self.object},
61-
),
62-
using=self.template_engine,
63-
content_type=self.content_type,
64-
)
50+
# If we are hashing the client secret, display the cleartext value in a flash message with
51+
# Django's messages framework
52+
if form.cleaned_data["hash_client_secret"]:
53+
messages.add_message(
54+
self.request,
55+
messages.SUCCESS,
56+
# Since the client_secret is not user-supplied, we can manually mark this entire
57+
# string as safe so Django doesn't re-encode the HTML markup
58+
mark_safe(
59+
_(
60+
"The application client secret is:<br /><code>%s</code><br />"
61+
"This will only be shown once, so copy it now!"
62+
)
63+
% form.instance.client_secret
64+
),
65+
)
66+
return super().form_valid(form)
6567

6668

6769
class ApplicationDetail(ApplicationOwnerIsUserMixin, DetailView):

0 commit comments

Comments
 (0)