0001-auth-separate-OIDC-providers-in-blocks-on-login-page.patch
src/authentic2/views.py | ||
---|---|---|
320 | 320 |
block['form'] = form_class() |
321 | 321 |
blocks.append(block) |
322 | 322 |
else: # New frontends API |
323 |
auth_blocks = [] |
|
323 | 324 |
parameters = {'request': request, |
324 | 325 |
'context': context} |
325 |
block = utils.get_authenticator_method(authenticator, 'login', parameters) |
|
326 |
# check if the authenticator has multiple instances |
|
327 |
if hasattr(authenticator, 'instances'): |
|
328 |
for instance_id, instance in authenticator.instances(**parameters): |
|
329 |
parameters['instance'] = instance |
|
330 |
block = utils.get_authenticator_method(authenticator, 'login', parameters) |
|
331 |
# update block id in order to separate instances |
|
332 |
block['id'] = '%s_%s' % (block['id'], instance_id) |
|
333 |
auth_blocks.append(block) |
|
334 |
else: |
|
335 |
auth_blocks.append(utils.get_authenticator_method(authenticator, 'login', parameters)) |
|
326 | 336 |
# If a login frontend method returns an HttpResponse with a status code != 200 |
327 | 337 |
# this response is returned. |
328 |
if block: |
|
329 |
if block['status_code'] != 200: |
|
330 |
return block['response'] |
|
331 |
blocks.append(block) |
|
332 |
if hasattr(authenticator, 'is_hidden'): |
|
333 |
blocks[-1]['is_hidden'] = authenticator.is_hidden(request) |
|
334 |
else: |
|
335 |
blocks[-1]['is_hidden'] = False |
|
338 |
for block in auth_blocks: |
|
339 |
if block: |
|
340 |
if block['status_code'] != 200: |
|
341 |
return block['response'] |
|
342 |
blocks.append(block) |
|
343 |
# TODO: remove attribute below after cleaning up the templates |
|
344 |
blocks[-1]['is_hidden'] = False |
|
336 | 345 | |
337 | 346 |
# Old frontends API |
338 | 347 |
for block in blocks: |
src/authentic2_auth_oidc/authenticators.py | ||
---|---|---|
30 | 30 |
def id(self): |
31 | 31 |
return 'oidc' |
32 | 32 | |
33 |
def instances(self, request, *args, **kwargs): |
|
34 |
for p in utils.get_providers(shown=True): |
|
35 |
yield (p.slug, p) |
|
36 | ||
33 | 37 |
def login(self, request, *args, **kwargs): |
34 | 38 |
context = kwargs.get('context', {}) |
35 |
context['providers'] = utils.get_providers(shown=True) |
|
36 |
return render(request, 'authentic2_auth_oidc/login.html', context) |
|
39 |
if kwargs.get('instance'): |
|
40 |
context['provider'] = kwargs['instance'] |
|
41 |
return render(request, 'authentic2_auth_oidc/login.html', context) |
src/authentic2_auth_oidc/templates/authentic2_auth_oidc/login.html | ||
---|---|---|
1 |
{% for provider in providers %} |
|
2 |
<p id="oidc-p-{% firstof provider.slug provider.name|slugify %}"> |
|
3 |
<a id="oidc-a-{% firstof provider.slug provider.name|slugify %}" |
|
4 |
href="{% url "oidc-login" pk=provider.pk %}?{{ request.GET.urlencode }}">{{ provider.name }}</a> |
|
5 |
</p> |
|
6 |
{% endfor %} |
|
1 |
<p id="oidc-p-{% firstof provider.slug provider.name|slugify %}"> |
|
2 |
<a id="oidc-a-{% firstof provider.slug provider.name|slugify %}" |
|
3 |
href="{% url "oidc-login" pk=provider.pk %}?{{ request.GET.urlencode }}">{{ provider.name }}</a> |
|
4 |
</p> |
tests/test_auth_oidc.py | ||
---|---|---|
304 | 304 |
return qs |
305 | 305 | |
306 | 306 | |
307 |
def test_providers_on_login_page(oidc_provider, app): |
|
308 |
response = app.get('/login/') |
|
309 |
# two frontends should be present on login page |
|
310 |
assert response.pyquery('p#oidc-p-oididp') |
|
311 |
OIDCProvider.objects.create( |
|
312 |
id=2, |
|
313 |
ou=get_default_ou(), |
|
314 |
name='OIDCIDP 2', |
|
315 |
slug='oidcidp-2', |
|
316 |
issuer='https://idp2.example.com/', |
|
317 |
authorization_endpoint='https://idp2.example.com/authorize', |
|
318 |
token_endpoint='https://idp2.example.com/token', |
|
319 |
end_session_endpoint='https://idp2.example.com/logout', |
|
320 |
userinfo_endpoint='https://idp*é.example.com/user_info', |
|
321 |
token_revocation_endpoint='https://idp2.example.com/revoke', |
|
322 |
max_auth_age=10, |
|
323 |
strategy=OIDCProvider.STRATEGY_CREATE, |
|
324 |
jwkset_json=None, |
|
325 |
idtoken_algo=OIDCProvider.ALGO_RSA, |
|
326 |
claims_parameter_supported=False |
|
327 |
) |
|
328 | ||
329 |
response = app.get('/login/') |
|
330 |
assert response.pyquery('p#oidc-p-oididp') |
|
331 |
assert response.pyquery('p#oidc-p-oidcidp-2') |
|
332 | ||
333 | ||
334 | ||
335 | ||
307 | 336 |
def test_sso(app, caplog, code, oidc_provider, oidc_provider_jwkset, login_url, login_callback_url, hooks): |
308 | 337 |
OU = get_ou_model() |
309 | 338 |
cassis = OU.objects.create(name='Cassis', slug='cassis') |
310 |
- |