Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / target / shibboleth.py @ 5bc77346

History | View | Annotate | Download (7.4 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 5ce3ce4f Sofia Papagiannaki
#
3 64cd4730 Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 64cd4730 Antony Chazapis
# without modification, are permitted provided that the following
5 64cd4730 Antony Chazapis
# conditions are met:
6 5ce3ce4f Sofia Papagiannaki
#
7 64cd4730 Antony Chazapis
#   1. Redistributions of source code must retain the above
8 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
9 64cd4730 Antony Chazapis
#      disclaimer.
10 5ce3ce4f Sofia Papagiannaki
#
11 64cd4730 Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
13 64cd4730 Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 64cd4730 Antony Chazapis
#      provided with the distribution.
15 5ce3ce4f Sofia Papagiannaki
#
16 64cd4730 Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 64cd4730 Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 64cd4730 Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 64cd4730 Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 64cd4730 Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 64cd4730 Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 64cd4730 Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 64cd4730 Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 64cd4730 Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 64cd4730 Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 64cd4730 Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 64cd4730 Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 5ce3ce4f Sofia Papagiannaki
#
29 64cd4730 Antony Chazapis
# The views and conclusions contained in the software and
30 64cd4730 Antony Chazapis
# documentation are those of the authors and should not be
31 64cd4730 Antony Chazapis
# interpreted as representing official policies, either expressed
32 64cd4730 Antony Chazapis
# or implied, of GRNET S.A.
33 64cd4730 Antony Chazapis
34 9d20fe23 Kostas Papadimitriou
from django.conf import settings as global_settings
35 18ffbee1 Sofia Papagiannaki
from django.utils.translation import ugettext as _
36 18ffbee1 Sofia Papagiannaki
from django.contrib import messages
37 dda2e499 Sofia Papagiannaki
from django.views.decorators.http import require_http_methods
38 ef20ea07 Sofia Papagiannaki
from django.http import HttpResponseRedirect
39 64cd4730 Antony Chazapis
40 3e0a032d Sofia Papagiannaki
from astakos.im.util import login_url
41 6a80a0ae Kostas Papadimitriou
from astakos.im.models import AstakosUser, AstakosUserAuthProvider, \
42 6a80a0ae Kostas Papadimitriou
    PendingThirdPartyUser
43 d2633501 Kostas Papadimitriou
from astakos.im import settings
44 3e0a032d Sofia Papagiannaki
from astakos.im.views.target import get_pending_key, \
45 3e0a032d Sofia Papagiannaki
    handle_third_party_signup, handle_third_party_login, \
46 3e0a032d Sofia Papagiannaki
    init_third_party_session
47 3e0a032d Sofia Papagiannaki
from astakos.im.views.decorators import cookie_fix, requires_auth_provider
48 64cd4730 Antony Chazapis
49 ae497612 Olga Brani
import astakos.im.messages as astakos_messages
50 ef20ea07 Sofia Papagiannaki
import logging
51 ef20ea07 Sofia Papagiannaki
52 ef20ea07 Sofia Papagiannaki
logger = logging.getLogger(__name__)
53 ef20ea07 Sofia Papagiannaki
54 dd5f8f4d Kostas Papadimitriou
55 6a80a0ae Kostas Papadimitriou
def migrate_eppn_to_remote_id(eppn, remote_id):
56 6a80a0ae Kostas Papadimitriou
    """
57 6a80a0ae Kostas Papadimitriou
    Retrieve active and pending accounts that are associated with shibboleth
58 6a80a0ae Kostas Papadimitriou
    using EPPN as the third party unique identifier update them by storing
59 6a80a0ae Kostas Papadimitriou
    REMOTE_USER value instead.
60 6a80a0ae Kostas Papadimitriou
    """
61 6a80a0ae Kostas Papadimitriou
    if eppn == remote_id:
62 6a80a0ae Kostas Papadimitriou
        return
63 6a80a0ae Kostas Papadimitriou
64 6a80a0ae Kostas Papadimitriou
    try:
65 6a80a0ae Kostas Papadimitriou
        provider = AstakosUserAuthProvider.objects.get(module='shibboleth',
66 6a80a0ae Kostas Papadimitriou
                                                       identifier=eppn)
67 6a80a0ae Kostas Papadimitriou
        msg = "Migrating user %r eppn (%s -> %s)"
68 6a80a0ae Kostas Papadimitriou
        logger.info(msg, provider.user.log_display, eppn, remote_id)
69 6a80a0ae Kostas Papadimitriou
        provider.identifier = remote_id
70 6a80a0ae Kostas Papadimitriou
        provider.save()
71 6a80a0ae Kostas Papadimitriou
    except AstakosUserAuthProvider.DoesNotExist:
72 6a80a0ae Kostas Papadimitriou
        pass
73 6a80a0ae Kostas Papadimitriou
74 6a80a0ae Kostas Papadimitriou
    pending_users = \
75 5bc77346 Giorgos Korfiatis
        PendingThirdPartyUser.objects.filter(third_party_identifier=eppn,
76 5bc77346 Giorgos Korfiatis
                                             provider='shibboleth')
77 6a80a0ae Kostas Papadimitriou
78 6a80a0ae Kostas Papadimitriou
    for pending in pending_users:
79 6a80a0ae Kostas Papadimitriou
        msg = "Migrating pending user %s eppn (%s -> %s)"
80 6a80a0ae Kostas Papadimitriou
        logger.info(msg, pending.email, eppn, remote_id)
81 6a80a0ae Kostas Papadimitriou
        pending.third_party_identifier = remote_id
82 6a80a0ae Kostas Papadimitriou
        pending.save()
83 6a80a0ae Kostas Papadimitriou
84 6a80a0ae Kostas Papadimitriou
    return remote_id
85 6a80a0ae Kostas Papadimitriou
86 6a80a0ae Kostas Papadimitriou
87 64cd4730 Antony Chazapis
class Tokens:
88 64cd4730 Antony Chazapis
    # these are mapped by the Shibboleth SP software
89 5ce3ce4f Sofia Papagiannaki
    SHIB_EPPN = "HTTP_EPPN"  # eduPersonPrincipalName
90 64cd4730 Antony Chazapis
    SHIB_NAME = "HTTP_SHIB_INETORGPERSON_GIVENNAME"
91 64cd4730 Antony Chazapis
    SHIB_SURNAME = "HTTP_SHIB_PERSON_SURNAME"
92 64cd4730 Antony Chazapis
    SHIB_CN = "HTTP_SHIB_PERSON_COMMONNAME"
93 64cd4730 Antony Chazapis
    SHIB_DISPLAYNAME = "HTTP_SHIB_INETORGPERSON_DISPLAYNAME"
94 64cd4730 Antony Chazapis
    SHIB_EP_AFFILIATION = "HTTP_SHIB_EP_AFFILIATION"
95 64cd4730 Antony Chazapis
    SHIB_SESSION_ID = "HTTP_SHIB_SESSION_ID"
96 ca828a10 Sofia Papagiannaki
    SHIB_MAIL = "HTTP_SHIB_MAIL"
97 830747d2 Kostas Papadimitriou
    SHIB_REMOTE_USER = "HTTP_REMOTE_USER"
98 64cd4730 Antony Chazapis
99 dd5f8f4d Kostas Papadimitriou
100 9d20fe23 Kostas Papadimitriou
@requires_auth_provider('shibboleth')
101 dda2e499 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
102 222305b7 Sofia Papagiannaki
@cookie_fix
103 8fb8d0cf Giorgos Korfiatis
def login(request,
104 8fb8d0cf Giorgos Korfiatis
          template='im/third_party_check_local.html',
105 8fb8d0cf Giorgos Korfiatis
          extra_context=None):
106 73fbaec4 Sofia Papagiannaki
107 0e79735c Kostas Papadimitriou
    init_third_party_session(request)
108 ef20ea07 Sofia Papagiannaki
    extra_context = extra_context or {}
109 ef20ea07 Sofia Papagiannaki
110 4e30244e Sofia Papagiannaki
    tokens = request.META
111 dd5f8f4d Kostas Papadimitriou
    third_party_key = get_pending_key(request)
112 d2633501 Kostas Papadimitriou
113 a53ee093 Kostas Papadimitriou
    shibboleth_headers = {}
114 a53ee093 Kostas Papadimitriou
    for token in dir(Tokens):
115 a53ee093 Kostas Papadimitriou
        if token == token.upper():
116 feebcc02 Kostas Papadimitriou
            shibboleth_headers[token] = request.META.get(getattr(Tokens,
117 feebcc02 Kostas Papadimitriou
                                                                 token),
118 feebcc02 Kostas Papadimitriou
                                                         'NOT_SET')
119 f3463a00 Kostas Papadimitriou
120 a53ee093 Kostas Papadimitriou
    # log shibboleth headers
121 a53ee093 Kostas Papadimitriou
    # TODO: info -> debug
122 a53ee093 Kostas Papadimitriou
    logger.info("shibboleth request: %r" % shibboleth_headers)
123 a53ee093 Kostas Papadimitriou
124 564a2292 Kostas Papadimitriou
    try:
125 6a80a0ae Kostas Papadimitriou
        eppn = tokens.get(Tokens.SHIB_EPPN, None)
126 6a80a0ae Kostas Papadimitriou
        user_id = tokens.get(Tokens.SHIB_REMOTE_USER)
127 c1f65a1e Kostas Papadimitriou
        fullname, first_name, last_name, email = None, None, None, None
128 9d20fe23 Kostas Papadimitriou
        if global_settings.DEBUG and not eppn:
129 6a80a0ae Kostas Papadimitriou
            user_id = getattr(global_settings, 'SHIBBOLETH_TEST_REMOTE_USER',
130 6a80a0ae Kostas Papadimitriou
                              None)
131 9d20fe23 Kostas Papadimitriou
            eppn = getattr(global_settings, 'SHIBBOLETH_TEST_EPPN', None)
132 c1f65a1e Kostas Papadimitriou
            fullname = getattr(global_settings, 'SHIBBOLETH_TEST_FULLNAME',
133 9d20fe23 Kostas Papadimitriou
                               None)
134 9d20fe23 Kostas Papadimitriou
135 6a80a0ae Kostas Papadimitriou
        if not user_id:
136 6a80a0ae Kostas Papadimitriou
            raise KeyError(_(astakos_messages.SHIBBOLETH_MISSING_USER_ID) % {
137 8c8e318d Kostas Papadimitriou
                'domain': settings.BASE_HOST,
138 31bc3a62 Kostas Papadimitriou
                'contact_email': settings.CONTACT_EMAIL
139 564a2292 Kostas Papadimitriou
            })
140 564a2292 Kostas Papadimitriou
        if Tokens.SHIB_DISPLAYNAME in tokens:
141 c1f65a1e Kostas Papadimitriou
            fullname = tokens[Tokens.SHIB_DISPLAYNAME]
142 564a2292 Kostas Papadimitriou
        elif Tokens.SHIB_CN in tokens:
143 c1f65a1e Kostas Papadimitriou
            fullname = tokens[Tokens.SHIB_CN]
144 c1f65a1e Kostas Papadimitriou
        if Tokens.SHIB_NAME in tokens:
145 c1f65a1e Kostas Papadimitriou
            first_name = tokens[Tokens.SHIB_NAME]
146 c1f65a1e Kostas Papadimitriou
        if Tokens.SHIB_SURNAME in tokens:
147 c1f65a1e Kostas Papadimitriou
            last_name = tokens[Tokens.SHIB_SURNAME]
148 c1f65a1e Kostas Papadimitriou
149 c1f65a1e Kostas Papadimitriou
        if fullname:
150 c1f65a1e Kostas Papadimitriou
            splitted = fullname.split(' ', 1)
151 c1f65a1e Kostas Papadimitriou
            if len(splitted) == 2:
152 c1f65a1e Kostas Papadimitriou
                first_name, last_name = splitted
153 c1f65a1e Kostas Papadimitriou
        fullname = '%s %s' % (first_name, last_name)
154 c1f65a1e Kostas Papadimitriou
155 c1f65a1e Kostas Papadimitriou
        if not any([first_name, last_name]) and \
156 5bc77346 Giorgos Korfiatis
                settings.SHIBBOLETH_REQUIRE_NAME_INFO:
157 c1f65a1e Kostas Papadimitriou
            raise KeyError(_(astakos_messages.SHIBBOLETH_MISSING_NAME))
158 564a2292 Kostas Papadimitriou
159 564a2292 Kostas Papadimitriou
    except KeyError, e:
160 564a2292 Kostas Papadimitriou
        # invalid shibboleth headers, redirect to login, display message
161 564a2292 Kostas Papadimitriou
        messages.error(request, e.message)
162 564a2292 Kostas Papadimitriou
        return HttpResponseRedirect(login_url(request))
163 564a2292 Kostas Papadimitriou
164 6a80a0ae Kostas Papadimitriou
    if settings.SHIBBOLETH_MIGRATE_EPPN:
165 6a80a0ae Kostas Papadimitriou
        migrate_eppn_to_remote_id(eppn, user_id)
166 6a80a0ae Kostas Papadimitriou
167 564a2292 Kostas Papadimitriou
    affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, 'Shibboleth')
168 564a2292 Kostas Papadimitriou
    email = tokens.get(Tokens.SHIB_MAIL, '')
169 6a80a0ae Kostas Papadimitriou
    provider_info = {'eppn': eppn, 'email': email, 'name': fullname,
170 6a80a0ae Kostas Papadimitriou
                     'headers': shibboleth_headers, 'user_id': user_id}
171 d2633501 Kostas Papadimitriou
172 64cd4730 Antony Chazapis
    try:
173 c8d89a3c Kostas Papadimitriou
        return handle_third_party_login(request, 'shibboleth',
174 6a80a0ae Kostas Papadimitriou
                                        user_id, provider_info,
175 c8d89a3c Kostas Papadimitriou
                                        affiliation, third_party_key)
176 8f5a3a06 Sofia Papagiannaki
    except AstakosUser.DoesNotExist, e:
177 c8d89a3c Kostas Papadimitriou
        third_party_key = get_pending_key(request)
178 c1f65a1e Kostas Papadimitriou
        user_info = {'affiliation': affiliation,
179 c1f65a1e Kostas Papadimitriou
                     'first_name': first_name,
180 c1f65a1e Kostas Papadimitriou
                     'last_name': last_name,
181 c1f65a1e Kostas Papadimitriou
                     'email': email}
182 6a80a0ae Kostas Papadimitriou
        return handle_third_party_signup(request, user_id, 'shibboleth',
183 dd5f8f4d Kostas Papadimitriou
                                         third_party_key,
184 dd5f8f4d Kostas Papadimitriou
                                         provider_info,
185 dd5f8f4d Kostas Papadimitriou
                                         user_info,
186 dd5f8f4d Kostas Papadimitriou
                                         template,
187 dd5f8f4d Kostas Papadimitriou
                                         extra_context)