Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / target / shibboleth.py @ 91bbc1a4

History | View | Annotate | Download (6.8 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 c630fee6 Kostas Papadimitriou
import json
35 c630fee6 Kostas Papadimitriou
36 64cd4730 Antony Chazapis
from django.http import HttpResponseBadRequest
37 18ffbee1 Sofia Papagiannaki
from django.utils.translation import ugettext as _
38 18ffbee1 Sofia Papagiannaki
from django.contrib import messages
39 18ffbee1 Sofia Papagiannaki
from django.template import RequestContext
40 dda2e499 Sofia Papagiannaki
from django.views.decorators.http import require_http_methods
41 ef20ea07 Sofia Papagiannaki
from django.http import HttpResponseRedirect
42 ef20ea07 Sofia Papagiannaki
from django.core.urlresolvers import reverse
43 c0b26605 Sofia Papagiannaki
from django.core.exceptions import ImproperlyConfigured
44 d2633501 Kostas Papadimitriou
from django.shortcuts import get_object_or_404
45 d2633501 Kostas Papadimitriou
46 d2633501 Kostas Papadimitriou
from urlparse import urlunsplit, urlsplit
47 64cd4730 Antony Chazapis
48 dd5f8f4d Kostas Papadimitriou
from astakos.im.util import prepare_response, get_context, login_url
49 73fbaec4 Sofia Papagiannaki
from astakos.im.views import (
50 73fbaec4 Sofia Papagiannaki
    requires_anonymous, render_response, requires_auth_provider)
51 ef20ea07 Sofia Papagiannaki
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL
52 ef20ea07 Sofia Papagiannaki
from astakos.im.models import AstakosUser, PendingThirdPartyUser
53 4e30244e Sofia Papagiannaki
from astakos.im.forms import LoginForm
54 4e30244e Sofia Papagiannaki
from astakos.im.activation_backends import get_backend, SimpleBackend
55 c630fee6 Kostas Papadimitriou
from astakos.im import auth_providers
56 d2633501 Kostas Papadimitriou
from astakos.im import settings
57 dd5f8f4d Kostas Papadimitriou
from astakos.im.target import add_pending_auth_provider, get_pending_key, \
58 dd5f8f4d Kostas Papadimitriou
    handle_third_party_signup
59 64cd4730 Antony Chazapis
60 ae497612 Olga Brani
import astakos.im.messages as astakos_messages
61 ef20ea07 Sofia Papagiannaki
import logging
62 ef20ea07 Sofia Papagiannaki
63 ef20ea07 Sofia Papagiannaki
logger = logging.getLogger(__name__)
64 ef20ea07 Sofia Papagiannaki
65 dd5f8f4d Kostas Papadimitriou
66 64cd4730 Antony Chazapis
class Tokens:
67 64cd4730 Antony Chazapis
    # these are mapped by the Shibboleth SP software
68 5ce3ce4f Sofia Papagiannaki
    SHIB_EPPN = "HTTP_EPPN"  # eduPersonPrincipalName
69 64cd4730 Antony Chazapis
    SHIB_NAME = "HTTP_SHIB_INETORGPERSON_GIVENNAME"
70 64cd4730 Antony Chazapis
    SHIB_SURNAME = "HTTP_SHIB_PERSON_SURNAME"
71 64cd4730 Antony Chazapis
    SHIB_CN = "HTTP_SHIB_PERSON_COMMONNAME"
72 64cd4730 Antony Chazapis
    SHIB_DISPLAYNAME = "HTTP_SHIB_INETORGPERSON_DISPLAYNAME"
73 64cd4730 Antony Chazapis
    SHIB_EP_AFFILIATION = "HTTP_SHIB_EP_AFFILIATION"
74 64cd4730 Antony Chazapis
    SHIB_SESSION_ID = "HTTP_SHIB_SESSION_ID"
75 ca828a10 Sofia Papagiannaki
    SHIB_MAIL = "HTTP_SHIB_MAIL"
76 64cd4730 Antony Chazapis
77 dd5f8f4d Kostas Papadimitriou
78 c630fee6 Kostas Papadimitriou
@requires_auth_provider('shibboleth', login=True)
79 dda2e499 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
80 ef20ea07 Sofia Papagiannaki
def login(
81 ef20ea07 Sofia Papagiannaki
    request,
82 d2633501 Kostas Papadimitriou
    template='im/third_party_check_local.html',
83 73fbaec4 Sofia Papagiannaki
    extra_context=None):
84 73fbaec4 Sofia Papagiannaki
85 ef20ea07 Sofia Papagiannaki
    extra_context = extra_context or {}
86 ef20ea07 Sofia Papagiannaki
87 4e30244e Sofia Papagiannaki
    tokens = request.META
88 dd5f8f4d Kostas Papadimitriou
    third_party_key = get_pending_key(request)
89 d2633501 Kostas Papadimitriou
90 6c8a3f7c Sofia Papagiannaki
    try:
91 6c8a3f7c Sofia Papagiannaki
        eppn = tokens.get(Tokens.SHIB_EPPN)
92 6c8a3f7c Sofia Papagiannaki
        if not eppn:
93 e24d0e0d Kostas Papadimitriou
            raise KeyError(_(astakos_messages.SHIBBOLETH_MISSING_EPPN) % {
94 e24d0e0d Kostas Papadimitriou
                'domain': settings.BASEURL,
95 e24d0e0d Kostas Papadimitriou
                'contact_email': settings.DEFAULT_CONTACT_EMAIL
96 e24d0e0d Kostas Papadimitriou
            })
97 6c8a3f7c Sofia Papagiannaki
        if Tokens.SHIB_DISPLAYNAME in tokens:
98 6c8a3f7c Sofia Papagiannaki
            realname = tokens[Tokens.SHIB_DISPLAYNAME]
99 6c8a3f7c Sofia Papagiannaki
        elif Tokens.SHIB_CN in tokens:
100 6c8a3f7c Sofia Papagiannaki
            realname = tokens[Tokens.SHIB_CN]
101 6c8a3f7c Sofia Papagiannaki
        elif Tokens.SHIB_NAME in tokens and Tokens.SHIB_SURNAME in tokens:
102 6c8a3f7c Sofia Papagiannaki
            realname = tokens[Tokens.SHIB_NAME] + ' ' + tokens[Tokens.SHIB_SURNAME]
103 6c8a3f7c Sofia Papagiannaki
        else:
104 1d59653f Kostas Papadimitriou
            if settings.SHIBBOLETH_REQUIRE_NAME_INFO:
105 1d59653f Kostas Papadimitriou
                raise KeyError(_(astakos_messages.SHIBBOLETH_MISSING_NAME))
106 1d59653f Kostas Papadimitriou
            else:
107 1d59653f Kostas Papadimitriou
                realname = ''
108 dd5f8f4d Kostas Papadimitriou
109 6c8a3f7c Sofia Papagiannaki
    except KeyError, e:
110 d2633501 Kostas Papadimitriou
        # invalid shibboleth headers, redirect to login, display message
111 2e90e3ec Kostas Papadimitriou
        messages.error(request, e.message)
112 dd5f8f4d Kostas Papadimitriou
        return HttpResponseRedirect(login_url(request))
113 d2633501 Kostas Papadimitriou
114 6c8a3f7c Sofia Papagiannaki
    affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '')
115 6c8a3f7c Sofia Papagiannaki
    email = tokens.get(Tokens.SHIB_MAIL, '')
116 4a1e3e53 Kostas Papadimitriou
    provider_info = {'eppn': eppn, 'email': email, 'name': realname}
117 dd5f8f4d Kostas Papadimitriou
    userid = eppn
118 d2633501 Kostas Papadimitriou
119 d2633501 Kostas Papadimitriou
    # an existing user accessed the view
120 d2633501 Kostas Papadimitriou
    if request.user.is_authenticated():
121 dd5f8f4d Kostas Papadimitriou
122 d2633501 Kostas Papadimitriou
        if request.user.has_auth_provider('shibboleth', identifier=eppn):
123 d2633501 Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
124 d2633501 Kostas Papadimitriou
125 d2633501 Kostas Papadimitriou
        # automatically add eppn provider to user
126 d2633501 Kostas Papadimitriou
        user = request.user
127 f432088a Kostas Papadimitriou
        if not request.user.can_add_auth_provider('shibboleth',
128 f432088a Kostas Papadimitriou
                                                  identifier=eppn):
129 91bbc1a4 Kostas Papadimitriou
            # TODO: handle existing uuid message separately
130 4a1e3e53 Kostas Papadimitriou
            messages.error(request, _(astakos_messages.AUTH_PROVIDER_ADD_FAILED) +
131 4a1e3e53 Kostas Papadimitriou
                          u' ' + _(astakos_messages.AUTH_PROVIDER_ADD_EXISTS))
132 f432088a Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
133 f432088a Kostas Papadimitriou
134 c630fee6 Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier=eppn,
135 4a1e3e53 Kostas Papadimitriou
                               affiliation=affiliation,
136 4a1e3e53 Kostas Papadimitriou
                               provider_info=provider_info)
137 4a1e3e53 Kostas Papadimitriou
        messages.success(request, astakos_messages.AUTH_PROVIDER_ADDED)
138 f432088a Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
139 d2633501 Kostas Papadimitriou
140 64cd4730 Antony Chazapis
    try:
141 d2633501 Kostas Papadimitriou
        # astakos user exists ?
142 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get_auth_provider_user(
143 d2633501 Kostas Papadimitriou
            'shibboleth',
144 d2633501 Kostas Papadimitriou
            identifier=eppn
145 ef20ea07 Sofia Papagiannaki
        )
146 18ffbee1 Sofia Papagiannaki
        if user.is_active:
147 dd5f8f4d Kostas Papadimitriou
148 d2633501 Kostas Papadimitriou
            # authenticate user
149 c72d5a13 Kostas Papadimitriou
            response = prepare_response(request,
150 18ffbee1 Sofia Papagiannaki
                                    user,
151 18ffbee1 Sofia Papagiannaki
                                    request.GET.get('next'),
152 18ffbee1 Sofia Papagiannaki
                                    'renew' in request.GET)
153 d72f07dc Kostas Papadimitriou
            messages.success(request, _(astakos_messages.LOGIN_SUCCESS))
154 dd5f8f4d Kostas Papadimitriou
            add_pending_auth_provider(request, third_party_key)
155 c72d5a13 Kostas Papadimitriou
            response.set_cookie('astakos_last_login_method', 'local')
156 c72d5a13 Kostas Papadimitriou
            return response
157 18ffbee1 Sofia Papagiannaki
        else:
158 c4b1a172 Kostas Papadimitriou
            message = user.get_inactive_message()
159 1f3b4b39 Sofia Papagiannaki
            messages.error(request, message)
160 dd5f8f4d Kostas Papadimitriou
            return HttpResponseRedirect(login_url(request))
161 d2633501 Kostas Papadimitriou
162 8f5a3a06 Sofia Papagiannaki
    except AstakosUser.DoesNotExist, e:
163 dd5f8f4d Kostas Papadimitriou
        user_info = {'affiliation': affiliation, 'realname': realname}
164 dd5f8f4d Kostas Papadimitriou
        return handle_third_party_signup(request, userid, 'shibboleth',
165 dd5f8f4d Kostas Papadimitriou
                                         third_party_key,
166 dd5f8f4d Kostas Papadimitriou
                                         provider_info,
167 dd5f8f4d Kostas Papadimitriou
                                         user_info,
168 dd5f8f4d Kostas Papadimitriou
                                         template,
169 dd5f8f4d Kostas Papadimitriou
                                         extra_context)