providers/oauth: add support for consent stage, cleanup
This commit is contained in:
parent
c97b946a00
commit
4d81172a48
|
@ -23,7 +23,7 @@ class OAuth2Provider(Provider, AbstractApplication):
|
|||
def html_setup_urls(self, request: HttpRequest) -> Optional[str]:
|
||||
"""return template and context modal with URLs for authorize, token, openid-config, etc"""
|
||||
return render_to_string(
|
||||
"oauth2_provider/setup_url_modal.html",
|
||||
"providers/oauth/setup_url_modal.html",
|
||||
{
|
||||
"provider": self,
|
||||
"authorize_url": request.build_absolute_uri(
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
{% extends "login/base.html" %}
|
||||
|
||||
{% load passbook_utils %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block card_title %}
|
||||
{% trans 'Authorize Application' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card %}
|
||||
<form method="POST" class="pf-c-form">
|
||||
{% csrf_token %}
|
||||
{% if not error %}
|
||||
{% csrf_token %}
|
||||
{% for field in form %}
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="pf-c-form__group">
|
||||
<p class="subtitle">
|
||||
{% blocktrans with remote=application.name %}
|
||||
You're about to sign into {{ remote }}.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>{% trans "Application requires following permissions" %}</p>
|
||||
<ul class="pf-c-list">
|
||||
{% for scope in scopes_descriptions %}
|
||||
<li>{{ scope }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{{ form.errors }}
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
<div class="pf-c-form__group">
|
||||
<p>
|
||||
{% blocktrans with user=user %}
|
||||
You are logged in as {{ user }}. Not you?
|
||||
{% endblocktrans %}
|
||||
<a href="{% url 'passbook_flows:default-invalidation' %}">{% trans 'Logout' %}</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
<input type="submit" class="pf-c-button pf-m-primary" name="allow" value="{% trans 'Continue' %}">
|
||||
<a href="{% back %}" class="pf-c-button pf-m-secondary">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
<div class="pf-c-form__group" style="display: none;" id="loading">
|
||||
<div class="pf-c-form__horizontal-group">
|
||||
<span class="pf-c-spinner" role="progressbar" aria-valuetext="Loading...">
|
||||
<span class="pf-c-spinner__clipper"></span>
|
||||
<span class="pf-c-spinner__lead-ball"></span>
|
||||
<span class="pf-c-spinner__tail-ball"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="login-group">
|
||||
<p class="subtitle">
|
||||
{% blocktrans with err=error.error %}Error: {{ err }}{% endblocktrans %}
|
||||
</p>
|
||||
<p>{{ error.description }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
document.querySelector("form").addEventListener("submit", (e) => {
|
||||
document.getElementById("loading").removeAttribute("style");
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1 +0,0 @@
|
|||
{% extends "base/skeleton.html" %}
|
|
@ -0,0 +1,20 @@
|
|||
{% extends 'login/form_with_user.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block beneath_form %}
|
||||
<div class="pf-c-form__group">
|
||||
<p>
|
||||
{% blocktrans with name=context.application.name %}
|
||||
You're about to sign into {{ name }}.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>{% trans "Application requires following permissions" %}</p>
|
||||
<ul class="pf-c-list">
|
||||
{% for scope in context.scope_descriptions %}
|
||||
<li>{{ scope }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{{ hidden_inputs }}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,9 +1,11 @@
|
|||
"""passbook OAuth2 Views"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.views import View
|
||||
from oauth2_provider.exceptions import OAuthToolkitError
|
||||
from oauth2_provider.scopes import get_scopes_backend
|
||||
from oauth2_provider.views.base import AuthorizationView
|
||||
from structlog import get_logger
|
||||
|
||||
|
@ -20,6 +22,7 @@ from passbook.flows.stage import StageView
|
|||
from passbook.flows.views import SESSION_KEY_PLAN
|
||||
from passbook.lib.utils.urls import redirect_with_qs
|
||||
from passbook.providers.oauth.models import OAuth2Provider
|
||||
from passbook.stages.consent.stage import PLAN_CONTEXT_CONSENT_TEMPLATE
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
@ -32,9 +35,10 @@ PLAN_CONTEXT_CODE_CHALLENGE = "code_challenge"
|
|||
PLAN_CONTEXT_CODE_CHALLENGE_METHOD = "code_challenge_method"
|
||||
PLAN_CONTEXT_SCOPE = "scope"
|
||||
PLAN_CONTEXT_NONCE = "nonce"
|
||||
PLAN_CONTEXT_SCOPE_DESCRIPTION = "scope_descriptions"
|
||||
|
||||
|
||||
class AuthorizationFlowInitView(AccessMixin, View):
|
||||
class AuthorizationFlowInitView(AccessMixin, LoginRequiredMixin, View):
|
||||
"""OAuth2 Flow initializer, checks access to application and starts flow"""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
@ -54,8 +58,11 @@ class AuthorizationFlowInitView(AccessMixin, View):
|
|||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
# Regardless, we start the planner and return to it
|
||||
planner = FlowPlanner(provider.authorization_flow)
|
||||
# planner.use_cache = False
|
||||
planner.allow_empty_flows = True
|
||||
# Save scope descriptions
|
||||
scopes = request.GET.get(PLAN_CONTEXT_SCOPE)
|
||||
all_scopes = get_scopes_backend().get_all_scopes()
|
||||
|
||||
plan = planner.plan(
|
||||
self.request,
|
||||
{
|
||||
|
@ -65,10 +72,15 @@ class AuthorizationFlowInitView(AccessMixin, View):
|
|||
PLAN_CONTEXT_REDIRECT_URI: request.GET.get(PLAN_CONTEXT_REDIRECT_URI),
|
||||
PLAN_CONTEXT_RESPONSE_TYPE: request.GET.get(PLAN_CONTEXT_RESPONSE_TYPE),
|
||||
PLAN_CONTEXT_STATE: request.GET.get(PLAN_CONTEXT_STATE),
|
||||
PLAN_CONTEXT_SCOPE: request.GET.get(PLAN_CONTEXT_SCOPE),
|
||||
PLAN_CONTEXT_SCOPE: scopes,
|
||||
PLAN_CONTEXT_NONCE: request.GET.get(PLAN_CONTEXT_NONCE),
|
||||
PLAN_CONTEXT_SCOPE_DESCRIPTION: [
|
||||
all_scopes[scope] for scope in scopes.split(" ")
|
||||
],
|
||||
PLAN_CONTEXT_CONSENT_TEMPLATE: "providers/oauth/consent.html",
|
||||
},
|
||||
)
|
||||
|
||||
plan.append(in_memory_stage(OAuth2Stage))
|
||||
self.request.session[SESSION_KEY_PLAN] = plan
|
||||
return redirect_with_qs(
|
||||
|
|
Reference in New Issue