0001-misc-remove-dead-authenticators-code-66853.patch
src/authentic2/app_settings.py | ||
---|---|---|
174 | 174 |
default=True, definition='Check username uniqueness on registration' |
175 | 175 |
), |
176 | 176 |
IDP_BACKENDS=(), |
177 |
AUTH_FRONTENDS=(), |
|
178 |
AUTH_FRONTENDS_KWARGS={}, |
|
179 | 177 |
VALID_REFERERS=Setting(default=(), definition='List of prefix to match referers'), |
180 | 178 |
A2_OPENED_SESSION_COOKIE_NAME=Setting(default='A2_OPENED_SESSION', definition='Authentic session open'), |
181 | 179 |
A2_OPENED_SESSION_COOKIE_DOMAIN=Setting(default=None), |
src/authentic2/apps/authenticators/models.py | ||
---|---|---|
102 | 102 |
'value': value, |
103 | 103 |
} |
104 | 104 | |
105 |
@property |
|
106 |
def priority(self): |
|
107 |
return self.order |
|
108 | ||
109 | 105 |
def shown(self, ctx=()): |
110 | 106 |
if not self.show_condition: |
111 | 107 |
return True |
src/authentic2/authenticators.py | ||
---|---|---|
1 |
# authentic2 - versatile identity manager |
|
2 |
# Copyright (C) 2010-2019 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
import logging |
|
18 | ||
19 |
from .utils.evaluate import evaluate_condition |
|
20 | ||
21 |
logger = logging.getLogger(__name__) |
|
22 | ||
23 | ||
24 |
class BaseAuthenticator: |
|
25 |
how = () |
|
26 | ||
27 |
def __init__(self, show_condition=None, **kwargs): |
|
28 |
self.show_condition = show_condition |
|
29 | ||
30 |
def get_show_condition(self, instance_id=None): |
|
31 |
if isinstance(self.show_condition, dict): |
|
32 |
if instance_id and instance_id in self.show_condition: |
|
33 |
return self.show_condition[instance_id] |
|
34 |
else: |
|
35 |
return self.show_condition |
|
36 | ||
37 |
def shown(self, instance_id=None, ctx=()): |
|
38 |
show_condition = self.get_show_condition(instance_id) |
|
39 |
if not show_condition: |
|
40 |
return True |
|
41 |
ctx = dict(ctx, id=instance_id) |
|
42 |
try: |
|
43 |
return evaluate_condition(show_condition, ctx, on_raise=True) |
|
44 |
except Exception as e: |
|
45 |
logger.error(e) |
|
46 |
return False |
|
47 | ||
48 |
def get_identifier(self): |
|
49 |
return self.id |
src/authentic2/settings.py | ||
---|---|---|
187 | 187 |
# Authentication settings |
188 | 188 |
########################### |
189 | 189 |
AUTH_USER_MODEL = 'custom_user.User' |
190 |
AUTH_FRONTENDS = plugins.register_plugins_authenticators() |
|
191 | 190 | |
192 | 191 |
########################### |
193 | 192 |
# RBAC settings |
src/authentic2/utils/misc.py | ||
---|---|---|
139 | 139 |
return list |
140 | 140 | |
141 | 141 | |
142 |
def load_backend(path, kwargs):
|
|
142 |
def load_backend(path): |
|
143 | 143 |
'''Load an IdP backend by its module path''' |
144 | 144 |
i = path.rfind('.') |
145 | 145 |
module, attr = path[:i], path[i + 1 :] |
... | ... | |
155 | 155 |
cls = getattr(mod, attr) |
156 | 156 |
except AttributeError: |
157 | 157 |
raise ImproperlyConfigured('Module "%s" does not define a "%s" idp backend' % (module, attr)) |
158 |
backend_kwargs = {} |
|
159 |
if hasattr(cls, 'id'): |
|
160 |
backend_kwargs.update(kwargs.get(cls.id, {})) |
|
161 |
return cls(**backend_kwargs) |
|
158 |
return cls() |
|
162 | 159 | |
163 | 160 | |
164 |
def get_backends(setting_name='IDP_BACKENDS'):
|
|
161 |
def get_backends(): |
|
165 | 162 |
'''Return the list of enabled cleaned backends.''' |
166 | 163 |
backends = [] |
167 |
if setting_name == 'AUTH_FRONTENDS': |
|
168 |
from authentic2.apps.authenticators.models import BaseAuthenticator, LoginPasswordAuthenticator |
|
169 | 164 | |
170 |
backends = list( |
|
171 |
BaseAuthenticator.authenticators.filter(enabled=True).exclude(slug='password-authenticator') |
|
172 |
) |
|
173 |
password_backend, dummy = LoginPasswordAuthenticator.objects.get_or_create( |
|
174 |
slug='password-authenticator', |
|
175 |
defaults={'enabled': True}, |
|
176 |
) |
|
177 |
if password_backend.enabled: |
|
178 |
backends.append(password_backend) |
|
179 | ||
180 |
for backend_path in getattr(app_settings, setting_name): |
|
165 |
for backend_path in app_settings.IDP_BACKENDS: |
|
181 | 166 |
kwargs = {} |
182 | 167 |
if not isinstance(backend_path, str): |
183 | 168 |
backend_path, kwargs = backend_path |
184 |
kwargs_settings = getattr(app_settings, setting_name + '_KWARGS', {}) |
|
185 |
backend = load_backend(backend_path, kwargs_settings) |
|
186 |
# If no enabled method is defined on the backend, backend enabled by default. |
|
187 |
if hasattr(backend, 'enabled') and not backend.enabled(): |
|
188 |
continue |
|
189 |
if backend_path in kwargs_settings: |
|
190 |
kwargs.update(kwargs_settings[backend_path]) |
|
191 |
# Clean id and name for legacy support |
|
192 |
if hasattr(backend, 'id'): |
|
193 |
if callable(backend.id): |
|
194 |
backend.id = backend.id() |
|
195 |
else: |
|
196 |
backend.id = None |
|
197 |
if hasattr(backend, 'name'): |
|
198 |
if callable(backend.name): |
|
199 |
backend.name = backend.name() |
|
200 |
else: |
|
201 |
backend.name = None |
|
202 |
if not hasattr(backend, 'priority'): |
|
203 |
backend.priority = 999 # backend with undefined priority go last |
|
204 |
if backend.id and backend.id in kwargs_settings: |
|
205 |
kwargs.update(kwargs_settings[backend.id]) |
|
169 |
backend = load_backend(backend_path) |
|
206 | 170 |
backend.__dict__.update(kwargs) |
207 | 171 |
backends.append(backend) |
208 |
# Order backends list with backend priority |
|
209 |
backends.sort(key=lambda backend: backend.priority) |
|
172 | ||
173 |
return backends |
|
174 | ||
175 | ||
176 |
def get_authenticators(): |
|
177 |
from authentic2.apps.authenticators.models import BaseAuthenticator, LoginPasswordAuthenticator |
|
178 | ||
179 |
backends = list( |
|
180 |
BaseAuthenticator.authenticators.filter(enabled=True).exclude(slug='password-authenticator') |
|
181 |
) |
|
182 |
password_backend, dummy = LoginPasswordAuthenticator.objects.get_or_create( |
|
183 |
slug='password-authenticator', |
|
184 |
defaults={'enabled': True}, |
|
185 |
) |
|
186 |
if password_backend.enabled: |
|
187 |
backends.append(password_backend) |
|
188 | ||
189 |
backends.sort(key=lambda backend: backend.order) |
|
210 | 190 |
return backends |
211 | 191 | |
212 | 192 |
src/authentic2/views.py | ||
---|---|---|
361 | 361 |
redirect_to = settings.LOGIN_REDIRECT_URL |
362 | 362 |
nonce = request.GET.get(constants.NONCE_FIELD_NAME) |
363 | 363 | |
364 |
authenticators = utils_misc.get_backends('AUTH_FRONTENDS')
|
|
364 |
authenticators = utils_misc.get_authenticators()
|
|
365 | 365 | |
366 | 366 |
blocks = [] |
367 | 367 | |
... | ... | |
382 | 382 |
for authenticator in authenticators: |
383 | 383 |
if methods and not set(authenticator.how) & set(methods): |
384 | 384 |
continue |
385 |
# Legacy API |
|
386 |
if not hasattr(authenticator, 'login'): |
|
387 |
fid = authenticator.get_identifier() |
|
388 |
name = authenticator.name |
|
389 |
form_class = authenticator.form() |
|
390 |
submit_name = 'submit-%s' % fid |
|
391 |
block = {'id': fid, 'name': name, 'authenticator': authenticator} |
|
392 |
if request.method == 'POST' and submit_name in request.POST: |
|
393 |
form = form_class(data=request.POST) |
|
394 |
if form.is_valid(): |
|
395 |
return authenticator.post(request, form, nonce, redirect_to) |
|
396 |
block['form'] = form |
|
397 |
else: |
|
398 |
block['form'] = form_class() |
|
399 |
blocks.append(block) |
|
400 |
else: # New frontends API |
|
401 |
auth_blocks = [] |
|
402 |
parameters = {'request': request, 'context': context} |
|
403 |
login_hint = set(request.session.get('login-hint', [])) |
|
404 |
show_ctx = make_condition_context(request=request, login_hint=login_hint) |
|
405 |
service = get_service(request) |
|
406 |
if service: |
|
407 |
show_ctx['service_ou_slug'] = service.ou and service.ou.slug |
|
408 |
show_ctx['service_slug'] = service.slug |
|
409 |
show_ctx['service'] = service |
|
410 |
else: |
|
411 |
show_ctx['service_ou_slug'] = '' |
|
412 |
show_ctx['service_slug'] = '' |
|
413 |
show_ctx['service'] = None |
|
414 |
# check if the authenticator has multiple instances |
|
415 |
if hasattr(authenticator, 'instances'): |
|
416 |
for instance_id, instance in authenticator.instances(**parameters): |
|
417 |
parameters['instance'] = instance |
|
418 |
parameters['instance_id'] = instance_id |
|
419 |
if not authenticator.shown(instance_id=instance_id, ctx=show_ctx): |
|
420 |
continue |
|
421 |
context['block_index'] = len(blocks) |
|
422 |
block = utils_misc.get_authenticator_method(authenticator, 'login', parameters) |
|
423 |
# update block id in order to separate instances |
|
424 |
block['id'] = '%s_%s' % (block['id'], instance_id) |
|
425 |
auth_blocks.append(block) |
|
426 |
else: |
|
427 |
if authenticator.shown(ctx=show_ctx): |
|
428 |
context['block_index'] = len(blocks) |
|
429 |
auth_blocks.append( |
|
430 |
utils_misc.get_authenticator_method(authenticator, 'login', parameters) |
|
431 |
) |
|
432 |
# If a login frontend method returns an HttpResponse with a status code != 200 |
|
433 |
# this response is returned. |
|
434 |
for block in auth_blocks: |
|
435 |
if block: |
|
436 |
if block['status_code'] != 200: |
|
437 |
return block['response'] |
|
438 |
blocks.append(block) |
|
385 |
auth_blocks = [] |
|
386 |
parameters = {'request': request, 'context': context} |
|
387 |
login_hint = set(request.session.get('login-hint', [])) |
|
388 |
show_ctx = make_condition_context(request=request, login_hint=login_hint) |
|
389 |
service = get_service(request) |
|
390 |
if service: |
|
391 |
show_ctx['service_ou_slug'] = service.ou and service.ou.slug |
|
392 |
show_ctx['service_slug'] = service.slug |
|
393 |
show_ctx['service'] = service |
|
394 |
else: |
|
395 |
show_ctx['service_ou_slug'] = '' |
|
396 |
show_ctx['service_slug'] = '' |
|
397 |
show_ctx['service'] = None |
|
398 |
if authenticator.shown(ctx=show_ctx): |
|
399 |
context['block_index'] = len(blocks) |
|
400 |
auth_blocks.append(utils_misc.get_authenticator_method(authenticator, 'login', parameters)) |
|
401 |
# If a login frontend method returns an HttpResponse with a status code != 200 |
|
402 |
# this response is returned. |
|
403 |
for block in auth_blocks: |
|
404 |
if block: |
|
405 |
if block['status_code'] != 200: |
|
406 |
return block['response'] |
|
407 |
blocks.append(block) |
|
439 | 408 | |
440 | 409 |
# run the only available authenticator if able to autorun |
441 | 410 |
if len(blocks) == 1: |
... | ... | |
455 | 424 |
context.update( |
456 | 425 |
{'submit_name': 'submit-%s' % fid, redirect_field_name: redirect_to, 'form': block['form']} |
457 | 426 |
) |
458 |
if hasattr(authenticator, 'get_context'): |
|
459 |
context.update(authenticator.get_context()) |
|
460 | 427 |
sub_template_name = authenticator.template() |
461 | 428 |
block['content'] = render_to_string(sub_template_name, context, request=request) |
462 | 429 | |
... | ... | |
512 | 479 | |
513 | 480 |
def get_context_data(self, **kwargs): |
514 | 481 |
context = super().get_context_data(**kwargs) |
515 |
frontends = utils_misc.get_backends('AUTH_FRONTENDS')
|
|
482 |
frontends = utils_misc.get_authenticators()
|
|
516 | 483 | |
517 | 484 |
request = self.request |
518 | 485 | |
... | ... | |
1163 | 1130 |
parameters = {'request': self.request, 'context': context} |
1164 | 1131 |
blocks = [ |
1165 | 1132 |
utils_misc.get_authenticator_method(authenticator, 'registration', parameters) |
1166 |
for authenticator in utils_misc.get_backends('AUTH_FRONTENDS')
|
|
1133 |
for authenticator in utils_misc.get_authenticators()
|
|
1167 | 1134 |
] |
1168 | 1135 |
context['frontends'] = collections.OrderedDict((block['id'], block) for block in blocks if block) |
1169 | 1136 |
return context |
1170 |
- |