root / snf-cyclades-app / synnefo / aai / middleware.py @ 9c0ac5af
History | View | Annotate | Download (5.3 kB)
1 | 48130e66 | Georgios Gousios | # Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 48130e66 | Georgios Gousios | #
|
3 | 48130e66 | Georgios Gousios | # Redistribution and use in source and binary forms, with or without
|
4 | 48130e66 | Georgios Gousios | # modification, are permitted provided that the following conditions
|
5 | 48130e66 | Georgios Gousios | # are met:
|
6 | 48130e66 | Georgios Gousios | #
|
7 | 48130e66 | Georgios Gousios | # 1. Redistributions of source code must retain the above copyright
|
8 | 48130e66 | Georgios Gousios | # notice, this list of conditions and the following disclaimer.
|
9 | 48130e66 | Georgios Gousios | #
|
10 | 48130e66 | Georgios Gousios | # 2. Redistributions in binary form must reproduce the above copyright
|
11 | 48130e66 | Georgios Gousios | # notice, this list of conditions and the following disclaimer in the
|
12 | 48130e66 | Georgios Gousios | # documentation and/or other materials provided with the distribution.
|
13 | 48130e66 | Georgios Gousios | #
|
14 | 48130e66 | Georgios Gousios | # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
15 | 48130e66 | Georgios Gousios | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16 | 48130e66 | Georgios Gousios | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17 | 48130e66 | Georgios Gousios | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
18 | 48130e66 | Georgios Gousios | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19 | 48130e66 | Georgios Gousios | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
20 | 48130e66 | Georgios Gousios | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
21 | 48130e66 | Georgios Gousios | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
22 | 48130e66 | Georgios Gousios | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
23 | 48130e66 | Georgios Gousios | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
24 | 48130e66 | Georgios Gousios | # SUCH DAMAGE.
|
25 | 48130e66 | Georgios Gousios | #
|
26 | 48130e66 | Georgios Gousios | # The views and conclusions contained in the software and documentation are
|
27 | 48130e66 | Georgios Gousios | # those of the authors and should not be interpreted as representing official
|
28 | 48130e66 | Georgios Gousios | # policies, either expressed or implied, of GRNET S.A.
|
29 | 48130e66 | Georgios Gousios | |
30 | ef39e7ee | Georgios Gousios | from django.conf import settings |
31 | ef39e7ee | Georgios Gousios | from django.http import HttpResponse, HttpResponseRedirect |
32 | 5032e934 | Faidon Liambotis | from django.utils.cache import patch_vary_headers |
33 | 89f86fd3 | Georgios Gousios | from synnefo.db.models import SynnefoUser |
34 | 8f377cd6 | Georgios Gousios | from synnefo.aai.shibboleth import Tokens, register_shibboleth_user |
35 | faa26af8 | Georgios Gousios | import time |
36 | 89f86fd3 | Georgios Gousios | |
37 | e26fb12b | Georgios Gousios | DONT_CHECK = getattr(settings, "AAI_SKIP_AUTH_URLS", ['/api', '/invitations/login']) |
38 | 5ac53b64 | Georgios Gousios | |
39 | 89f86fd3 | Georgios Gousios | class SynnefoAuthMiddleware(object): |
40 | 89f86fd3 | Georgios Gousios | |
41 | 89f86fd3 | Georgios Gousios | def process_request(self, request): |
42 | c06de383 | Georgios Gousios | |
43 | 1b68fa48 | Georgios Gousios | for path in DONT_CHECK: |
44 | 1b68fa48 | Georgios Gousios | if request.path.startswith(path):
|
45 | 1b68fa48 | Georgios Gousios | return
|
46 | def2c5c1 | Georgios Gousios | |
47 | 89b6b240 | Georgios Gousios | # Special case for testing purposes, delivers the cookie for the
|
48 | 89b6b240 | Georgios Gousios | # test user on first access
|
49 | 6ff84e93 | Georgios Gousios | if settings.BYPASS_AUTHENTICATION and \ |
50 | 6ff84e93 | Georgios Gousios | request.GET.get('test') is not None: |
51 | 34d1013b | Vangelis Koukis | try:
|
52 | 34d1013b | Vangelis Koukis | u = SynnefoUser.objects.get( |
53 | 34d1013b | Vangelis Koukis | auth_token=settings.BYPASS_AUTHENTICATION_SECRET_TOKEN) |
54 | 34d1013b | Vangelis Koukis | except SynnefoUser.DoesNotExist:
|
55 | 34d1013b | Vangelis Koukis | raise Exception("No user found with token matching " |
56 | 34d1013b | Vangelis Koukis | "BYPASS_AUTHENTICATION_SECRET_TOKEN.")
|
57 | c9fdfa27 | Georgios Gousios | return self._redirect_shib_auth_user(user = u) |
58 | 89b6b240 | Georgios Gousios | |
59 | c06de383 | Georgios Gousios | token = None
|
60 | c06de383 | Georgios Gousios | |
61 | 5563866c | Georgios Gousios | # Try to find token in a cookie
|
62 | d01e6404 | Faidon Liambotis | token = request.COOKIES.get('X-Auth-Token', None) |
63 | c06de383 | Georgios Gousios | |
64 | 5563866c | Georgios Gousios | # Try to find token in request header
|
65 | c06de383 | Georgios Gousios | if not token: |
66 | c06de383 | Georgios Gousios | token = request.META.get('HTTP_X_AUTH_TOKEN', None) |
67 | c06de383 | Georgios Gousios | |
68 | 40777cc8 | Giorgos Verigakis | if token:
|
69 | d01e6404 | Faidon Liambotis | # token was found, retrieve user from backing store
|
70 | faa26af8 | Georgios Gousios | try:
|
71 | 40777cc8 | Giorgos Verigakis | user = SynnefoUser.objects.get(auth_token=token) |
72 | 5563866c | Georgios Gousios | |
73 | faa26af8 | Georgios Gousios | except SynnefoUser.DoesNotExist:
|
74 | 79d8af70 | Georgios Gousios | return HttpResponseRedirect(settings.LOGIN_URL)
|
75 | d01e6404 | Faidon Liambotis | # check user's auth token validity
|
76 | faa26af8 | Georgios Gousios | if (time.time() -
|
77 | c9fdfa27 | Georgios Gousios | time.mktime(user.auth_token_expires.timetuple())) > 0:
|
78 | d01e6404 | Faidon Liambotis | # the user's token has expired, prompt to re-login
|
79 | 79d8af70 | Georgios Gousios | return HttpResponseRedirect(settings.LOGIN_URL)
|
80 | faa26af8 | Georgios Gousios | |
81 | 89f86fd3 | Georgios Gousios | request.user = user |
82 | ef39e7ee | Georgios Gousios | return
|
83 | 89f86fd3 | Georgios Gousios | |
84 | d01e6404 | Faidon Liambotis | # token was not found but user authenticated by Shibboleth
|
85 | d01e6404 | Faidon Liambotis | if Tokens.SHIB_EPPN in request.META and \ |
86 | d01e6404 | Faidon Liambotis | Tokens.SHIB_SESSION_ID in request.META:
|
87 | 1896d262 | Georgios Gousios | try:
|
88 | d01e6404 | Faidon Liambotis | user = SynnefoUser.objects.get(uniq=request.META[Tokens.SHIB_EPPN]) |
89 | d01e6404 | Faidon Liambotis | return self._redirect_shib_auth_user(user) |
90 | 1896d262 | Georgios Gousios | except SynnefoUser.DoesNotExist:
|
91 | dbf97ed2 | Georgios Gousios | if register_shibboleth_user(request.META):
|
92 | d01e6404 | Faidon Liambotis | user = SynnefoUser.objects.get(uniq=request.META[Tokens.SHIB_EPPN]) |
93 | ac3c3a4b | Georgios Gousios | return self._redirect_shib_auth_user(user) |
94 | 57e59589 | Georgios Gousios | else:
|
95 | 79d8af70 | Georgios Gousios | return HttpResponseRedirect(settings.LOGIN_URL)
|
96 | dbf97ed2 | Georgios Gousios | |
97 | d01e6404 | Faidon Liambotis | if settings.TEST and 'TEST-AAI' in request.META: |
98 | 79d8af70 | Georgios Gousios | return HttpResponseRedirect(settings.LOGIN_URL)
|
99 | 25380811 | Georgios Gousios | |
100 | 79d8af70 | Georgios Gousios | if request.path.endswith(settings.LOGIN_URL):
|
101 | d01e6404 | Faidon Liambotis | # avoid redirect loops
|
102 | d01e6404 | Faidon Liambotis | return
|
103 | 8f377cd6 | Georgios Gousios | else:
|
104 | d01e6404 | Faidon Liambotis | # no authentication info found in headers, redirect back
|
105 | 79d8af70 | Georgios Gousios | return HttpResponseRedirect(settings.LOGIN_URL)
|
106 | dd53338a | Georgios Gousios | |
107 | dd53338a | Georgios Gousios | def process_response(self, request, response): |
108 | d01e6404 | Faidon Liambotis | # Tell proxies and other interested parties that the request varies
|
109 | d01e6404 | Faidon Liambotis | # based on X-Auth-Token, to avoid caching of results
|
110 | 5032e934 | Faidon Liambotis | patch_vary_headers(response, ('X-Auth-Token',))
|
111 | dd53338a | Georgios Gousios | return response
|
112 | 63efc637 | Georgios Gousios | |
113 | ac3c3a4b | Georgios Gousios | def _redirect_shib_auth_user(self, user): |
114 | c9fdfa27 | Georgios Gousios | expire_fmt = user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
|
115 | c06de383 | Georgios Gousios | |
116 | ac3c3a4b | Georgios Gousios | response = HttpResponse() |
117 | 4733c1b0 | Georgios Gousios | response.set_cookie('X-Auth-Token', value=user.auth_token,
|
118 | 4733c1b0 | Georgios Gousios | expires=expire_fmt, path='/')
|
119 | d01e6404 | Faidon Liambotis | response['X-Auth-Token'] = user.auth_token
|
120 | ac3c3a4b | Georgios Gousios | response['Location'] = settings.APP_INSTALL_URL
|
121 | ac3c3a4b | Georgios Gousios | response.status_code = 302
|
122 | ac3c3a4b | Georgios Gousios | return response
|
123 | 5ac53b64 | Georgios Gousios | |
124 | 5ac53b64 | Georgios Gousios | |
125 | 5ac53b64 | Georgios Gousios | def add_url_exception(url): |
126 | 5ac53b64 | Georgios Gousios | if not url in DONT_CHECK: |
127 | 5ac53b64 | Georgios Gousios | DONT_CHECK.append(url) |