Projet

Général

Profil

0002-profile-add-csam-account-un-linking-capabilities-608.patch

Paul Marillonnet, 24 janvier 2022 18:13

Télécharger (7,15 ko)

Voir les différences:

Subject: [PATCH 2/2] profile: add csam account-(un)linking capabilities
 (#60837)

 src/authentic2_auth_fedict/authenticators.py  |  2 -
 src/authentic2_auth_fedict/backends.py        | 48 +++++++++++++++++++
 .../authentic2_auth_fedict/profile.html       | 27 +++++++++--
 src/authentic2_auth_fedict/urls.py            |  1 +
 src/authentic2_auth_fedict/views.py           | 16 ++++++-
 5 files changed, 88 insertions(+), 6 deletions(-)
src/authentic2_auth_fedict/authenticators.py
49 49
    def profile(self, request, *args, **kwargs):
50 50
        context = kwargs.get('context', {}).copy()
51 51
        user_saml_identifiers = request.user.saml_identifiers.all()
52
        if not user_saml_identifiers:
53
            return ''
54 52
        for user_saml_identifier in user_saml_identifiers:
55 53
            user_saml_identifier.idp = get_idp(user_saml_identifier.issuer)
56 54
        context['user_saml_identifiers'] = user_saml_identifiers
src/authentic2_auth_fedict/backends.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import logging
18

  
17 19
import lasso
20
from django.contrib import messages
21
from django.utils.translation import ugettext_lazy as _
18 22
from mellon.backends import SAMLBackend
23
from mellon.utils import get_adapters, get_idp
24

  
25
logger = logging.getLogger(__name__)
19 26

  
20 27

  
21 28
class FedictBackend(SAMLBackend):
......
28 35
        # but we do not expose this detail to the service provider as all it
29 36
        # needs to know is "strong authentication".
30 37
        return lasso.SAML2_AUTHN_CONTEXT_SMARTCARD_PKI
38

  
39
    def authenticate(self, request=None, **credentials):
40
        saml_attributes = credentials.get('saml_attributes') or {}
41
        if 'issuer' not in saml_attributes:
42
            logger.debug('no idp in saml_attributes')
43
            return None
44
        idp = get_idp(saml_attributes['issuer'])
45
        if not idp:
46
            logger.debug('unknown idp %s', saml_attributes['issuer'])
47
            return None
48
        adapters = get_adapters(idp, request=request)
49
        for adapter in adapters:
50
            if not hasattr(adapter, 'authorize'):
51
                continue
52
            if not adapter.authorize(idp, saml_attributes):
53
                return
54
        for adapter in adapters:
55
            if hasattr(adapter, 'lookup_by_attributes'):
56
                user = adapter.lookup_by_attributes(idp, saml_attributes)
57
        for adapter in adapters:
58
            if not hasattr(adapter, 'lookup_user'):
59
                continue
60
            user = adapter.lookup_user(idp, saml_attributes)
61
            if user:
62
                request_user = getattr(request, 'user', None) if request else None
63
                if request_user != user and request_user.is_authenticated:
64
                    messages.warning(request, _('Your account is now linked to your eID card.'))
65
                    saml_identifier = user.saml_identifier
66
                    saml_identifier.user = request_user
67
                    saml_identifier.save(update_fields=['user'])
68
                    user.mark_as_inactive(reason='fedict link to manually-created account')
69
                    user = request_user
70
                    user.saml_identifier = saml_identifier
71
                break
72
        else:  # no user found
73
            return
74
        for adapter in adapters:
75
            if not hasattr(adapter, 'provision'):
76
                continue
77
            adapter.provision(user, idp, saml_attributes)
78
        return user
src/authentic2_auth_fedict/templates/authentic2_auth_fedict/profile.html
1
<p>
2
Ce compte est relié à votre carte d'identité électronique.
3
</p>
1
{% load i18n static %}
2
<div>
3
 <img src="{% static "authentic2_auth_fedict/img/beid_image_mini.png" %}" alt="">
4
{% if user_saml_identifiers %}
5
 <p>{% blocktrans %}This account is linked to your eID card.{% endblocktrans %}</p>
6
 <p>
7
 {% blocktrans %}
8
 You may want to unlink your account, although you will not be able to
9
 connect to your account using your eID card (without re-doing the linking
10
 procedure).
11
 {% endblocktrans %}
12
 </p>
13
 <p><a class="button" href="{% url "fedict-unlink" %}">{% trans "Unlink my account" %}</a></p>
14
{% else %}
15
 <p>
16
 {% blocktrans %}
17
 You may want to link your existing Publik account to your eID. In order to
18
 do so, you will either need your eID card and its card reader
19
 or your list of personal tokens.
20
 {% endblocktrans %}
21
 </p>
22
 <p><a class="button" href="{% url "fedict-login" %}?next=/accounts/">{% trans "Link my account to my eID card" %}</a></p>
23
{% endif %}
24
</div>
src/authentic2_auth_fedict/urls.py
21 21
urlpatterns = [
22 22
    url(r'^accounts/saml/', include('mellon.urls')),
23 23
    url(r'^accounts/fedict/login/$', views.login, name='fedict-login'),
24
    url(r'^accounts/fedict/unlink/$', views.unlink, name='fedict-unlink'),
24 25
]
src/authentic2_auth_fedict/views.py
18 18
import urllib.parse
19 19

  
20 20
from django.conf import settings
21
from django.contrib import messages
21 22
from django.core import signing
22 23
from django.db import transaction
23 24
from django.http import HttpResponseRedirect
24
from django.shortcuts import resolve_url
25
from django.shortcuts import redirect, resolve_url
25 26
from django.urls import reverse
27
from django.utils.translation import ugettext_lazy as _
26 28
from django.views.decorators.csrf import csrf_exempt
27 29
from django.views.generic import View
28 30

  
......
69 71

  
70 72

  
71 73
login = transaction.non_atomic_requests(csrf_exempt(LoginView.as_view()))
74

  
75

  
76
def unlink(request):
77
    if not hasattr(request, 'user') or not hasattr(request.user, 'saml_identifiers'):
78
        return
79
    unlink_performed = False
80
    for saml_identifier in request.user.saml_identifiers.all():
81
        saml_identifier.delete()
82
        unlink_performed = True
83
    if unlink_performed:
84
        messages.success(request, message=_('Unlinking complete.'))
85
    return redirect('account_management')
72
-