0001-idp_oidc-revoke-oidc-claims-authorization-45200.patch
src/authentic2/templates/authentic2/accounts_authorized_oauth_services.html | ||
---|---|---|
1 |
{% extends "authentic2/base-page.html" %} |
|
2 |
{% load i18n %} |
|
3 | ||
4 |
{% block page-title %} |
|
5 |
{{ block.super }} - {{ view.title }} |
|
6 |
{% endblock %} |
|
7 | ||
8 |
{% block breadcrumb %} |
|
9 |
{{ block.super }} |
|
10 |
<a href="..">{% trans "Your account" %}</a> |
|
11 |
<a href="">{{ view.title }}</a> |
|
12 |
{% endblock %} |
|
13 | ||
14 |
{% block content %} |
|
15 |
{% block oidc-authorized-oauth-services-pre %}{% endblock %} |
|
16 |
<div id="oidc-authorized-oauth-services" class="authorized-oauth-services"> |
|
17 |
{% block oidc-authorized-oauth-services-top %} |
|
18 |
<span class="authorized-oauth-services-top"> |
|
19 |
{% if authorized_oauth_services|length_is:0 %} |
|
20 |
{% trans "You have not granted service access to your account." %} |
|
21 |
{% else %} |
|
22 |
{% blocktrans count counter=authorized_oauth_services|length %} |
|
23 |
You have granted only one service access to your account. |
|
24 |
{% plural %} |
|
25 |
You have granted {{ counter }} services access to your account. |
|
26 |
{% endblocktrans %} |
|
27 |
{% endif %} |
|
28 |
</span> |
|
29 |
{% endblock %} |
|
30 |
<ul> |
|
31 |
{% for auth in authorized_oauth_services %} |
|
32 |
<li> |
|
33 |
<form method="post"> |
|
34 |
{% block oidc-authorized-oauth-service-top %}{% endblock %} |
|
35 |
<span class="oidc-authorized-oauth-service-client"> |
|
36 |
{{ auth.client }} |
|
37 |
</span> |
|
38 |
<span class="oidc-authorized-oauth-service-dates"> |
|
39 |
{% trans "Allowed since: " %} |
|
40 |
<span class="time"> |
|
41 |
{{ auth.created }} |
|
42 |
</span> |
|
43 |
</span> |
|
44 |
/ |
|
45 |
<span class="oidc-authorized-oauth-service-expired"> |
|
46 |
{% trans "Expire on: " %} |
|
47 |
<span class="time"> |
|
48 |
{{ auth.expired }} |
|
49 |
</span> |
|
50 |
</span> |
|
51 |
{% csrf_token %} |
|
52 |
<input type="hidden" id="auth-id" name="auth_id" value="{{ auth.id }}"> |
|
53 |
<button class="delete-button">{% trans 'Revoke' %}</button> |
|
54 |
</form> |
|
55 |
{% block oidc-authorized-oauth-service-bottom %}{% endblock %} |
|
56 |
</li> |
|
57 |
{% endfor %} |
|
58 |
</ul> |
|
59 |
</table> |
|
60 |
{% block oidc-authorized-oauth-services-bottom %}{% endblock %} |
|
61 |
</div> |
|
62 |
{% block oidc-authorized-oauth-services-post %}{% endblock %} |
|
63 |
{% endblock %} |
src/authentic2/urls.py | ||
---|---|---|
64 | 64 |
views.edit_profile, |
65 | 65 |
name='profile_edit_with_scope'), |
66 | 66 |
url(r'^change-email/$', |
67 | 67 |
views.email_change, |
68 | 68 |
name='email-change'), |
69 | 69 |
url(r'^change-email/verify/$', |
70 | 70 |
views.email_change_verify, |
71 | 71 |
name='email-change-verify'), |
72 |
url(r'^authorizations/$', |
|
73 |
login_required(views.authorized_oauth_services), |
|
74 |
name='authorized-oauth-services'), |
|
72 | 75 |
url(r'^$', |
73 | 76 |
views.profile, |
74 | 77 |
name='account_management'), |
75 | 78 | |
76 | 79 |
# Password change |
77 | 80 |
url(r'^password/change/$', |
78 | 81 |
views.password_change, |
79 | 82 |
name='password_change'), |
src/authentic2/views.py | ||
---|---|---|
50 | 50 |
from django.http import Http404 |
51 | 51 |
from django.utils.http import urlsafe_base64_decode |
52 | 52 |
from django.views.generic.edit import CreateView |
53 | 53 |
from django.forms import CharField |
54 | 54 |
from django.http import HttpResponseBadRequest |
55 | 55 |
from django.template import loader |
56 | 56 | |
57 | 57 |
from authentic2.compat.misc import default_token_generator |
58 |
from authentic2_idp_oidc.models import OIDCAuthorization |
|
58 | 59 |
from . import (utils, app_settings, decorators, constants, |
59 | 60 |
models, cbv, hooks, validators) |
60 | 61 |
from .utils import switch_user |
61 | 62 |
from .a2_rbac.utils import get_default_ou |
62 | 63 |
from .a2_rbac.models import OrganizationalUnit as OU |
63 | 64 |
from .forms import ( |
64 | 65 |
passwords as passwords_forms, |
65 | 66 |
registration as registration_forms, |
... | ... | |
1264 | 1265 |
class SuView(View): |
1265 | 1266 |
def get(self, request, uuid): |
1266 | 1267 |
user = switch_user.resolve_token(uuid) |
1267 | 1268 |
if not user: |
1268 | 1269 |
raise Http404 |
1269 | 1270 |
return utils.simulate_authentication(request, user, 'su') |
1270 | 1271 | |
1271 | 1272 |
su = SuView.as_view() |
1273 | ||
1274 | ||
1275 |
class AuthorizedOauthServicesView(TemplateView): |
|
1276 |
template_name = 'authentic2/accounts_authorized_oauth_services.html' |
|
1277 |
title = _('Consent Management') |
|
1278 | ||
1279 |
def get_context_data(self, **kwargs): |
|
1280 |
context = super(AuthorizedOauthServicesView, self).get_context_data(**kwargs) |
|
1281 |
context['authorized_oauth_services'] = OIDCAuthorization.objects.filter( |
|
1282 |
user=self.request.user) |
|
1283 |
return context |
|
1284 | ||
1285 |
def post(self, request, *args, **kwargs): |
|
1286 |
if request.user: |
|
1287 |
qs = OIDCAuthorization.objects.filter(user=request.user) |
|
1288 |
auth_id = request.POST.get('auth_id') |
|
1289 |
if auth_id: |
|
1290 |
qs = qs.filter(id=auth_id) |
|
1291 |
qs.delete() |
|
1292 |
return HttpResponseRedirect(reverse('authorized-oauth-services')) |
|
1293 | ||
1294 | ||
1295 |
authorized_oauth_services = AuthorizedOauthServicesView.as_view() |
tests/test_idp_oidc.py | ||
---|---|---|
1599 | 1599 |
with pytest.raises(ValidationError, match=r'same domain'): |
1600 | 1600 |
OIDCClient( |
1601 | 1601 |
redirect_uris='https://example.com/ https://example2.com/', |
1602 | 1602 |
identifier_policy=OIDCClient.POLICY_PAIRWISE).clean() |
1603 | 1603 | |
1604 | 1604 |
OIDCClient( |
1605 | 1605 |
redirect_uris='https://example.com/ https://example2.com/', |
1606 | 1606 |
sector_identifier_uri='https://example.com/').clean() |
1607 | ||
1608 | ||
1609 |
def test_oidc_authorized_oauth_services_view(app, oidc_client, simple_user): |
|
1610 |
url = make_url('authorized-oauth-services') |
|
1611 |
response = app.get(url, status=302) |
|
1612 |
assert '/login/' in response.location |
|
1613 | ||
1614 |
utils.login(app, simple_user) |
|
1615 |
response = app.get(url, status=200) |
|
1616 |
assert "You have not granted service access to your account." in response.text |
|
1617 | ||
1618 |
OIDCAuthorization.objects.create( |
|
1619 |
client=oidc_client, user=simple_user, scopes='openid', |
|
1620 |
expired=now() + datetime.timedelta(days=2)) |
|
1621 |
OIDCAuthorization.objects.create( |
|
1622 |
client=oidc_client, user=simple_user, scopes='openid profile', |
|
1623 |
expired=now() + datetime.timedelta(days=2)) |
|
1624 |
OIDCAuthorization.objects.create( |
|
1625 |
client=oidc_client, user=simple_user, scopes='openid profile email', |
|
1626 |
expired=now() + datetime.timedelta(days=2)) |
|
1627 | ||
1628 |
response = app.get(url, status=200) |
|
1629 |
assert "You have granted 3 services access to your account." |
|
1630 |
assert len(response.html.find_all('button', {'class': 'delete-button'})) == 3 |
|
1631 | ||
1632 |
# revoke two |
|
1633 |
response = response.forms[0].submit() |
|
1634 |
response = response.follow() |
|
1635 |
assert len(response.html.find_all('button', {'class': 'delete-button'})) == 2 |
|
1636 |
response = response.forms[0].submit() |
|
1637 |
response = response.follow() |
|
1638 |
assert len(response.html.find_all('button', {'class': 'delete-button'})) == 1 |
|
1639 |
assert "You have only one granted service access to your account." not in response.text |
|
1607 |
- |