Statistics
| Branch: | Tag: | Revision:

root / aai / middleware.py @ ac3c3a4b

History | View | Annotate | Download (4.1 kB)

1
from time import time
2
from django.conf import settings
3
from django.http import HttpResponse, HttpResponseRedirect
4
from synnefo.db.models import SynnefoUser
5
from synnefo.aai.shibboleth import Tokens, register_shibboleth_user
6
import time
7

    
8
class SynnefoAuthMiddleware(object):
9

    
10
    auth_token = "X-Auth-Token"
11
    auth_user  = "X-Auth-User"
12
    auth_key   = "X-Auth-Key"
13

    
14
    def process_request(self, request):
15
        if self.auth_token in request.META:
16
            user = None
17
            #Retrieve user from DB or other caching mechanism
18
            try:
19
                user = SynnefoUser.objects.get(auth_token = request.META[self.auth_token])
20
            except SynnefoUser.DoesNotExist:
21
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
22

    
23
            #Check user's auth token
24
            if (time.time() -
25
                time.mktime(user.auth_token_created.timetuple()) +
26
                settings.AUTH_TOKEN_DURATION * 3600) > 0:
27
                #The user's token has expired, re-login
28
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
29

    
30
            request.user = user
31
            return
32

    
33
        #A user authenticated by Shibboleth, must include a uniq id
34
        if Tokens.SIB_EPPN in request.META and Tokens.SIB_SESSION_ID in request.META:
35
            user = None
36
            try:
37
                user = SynnefoUser.objects.get(
38
                    uniq = request.META[Tokens.SIB_EPPN])
39
            except SynnefoUser.DoesNotExist:
40
                pass
41

    
42
            #No user with this id could be found in the database
43
            if user is None:
44
                #Attempt to register the incoming user
45
                if register_shibboleth_user(request.META):
46
                    user = SynnefoUser.objects.get(
47
                        uniq = request.META[Tokens.SIB_EPPN])
48
                    return self._redirect_shib_auth_user(user)
49
                else:
50
                    return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
51

    
52
            #User and authentication token valid, user allowed to proceed
53
            return self._redirect_shib_auth_user(user)
54

    
55
        #An API authentication request
56
        if self.auth_user in request.META and self.auth_key in request.META and 'GET' == request.method:
57
            # This is here merely for compatibility with the Openstack API.
58
            # All normal users should authenticate through Sibbolleth. Admin
59
            # users or other selected users could use this as a bypass
60
            # mechanism
61
            user = SynnefoUser.objects\
62
                    .filter(name = request.META[self.auth_user]) \
63
                    .filter(uniq = request.META[self.auth_key])
64

    
65
            response = HttpResponse()
66
            if user.count() <= 0:
67
                response.status_code = 401
68
            else:
69
                response.status_code = 204
70
                response['X-Auth-Token'] = user[0].auth_token
71
                #TODO: set the following fields when we do have this info
72
                response['X-Server-Management-Url'] = ""
73
                response['X-Storage-Url'] = ""
74
                response['X-CDN-Management-Url'] = ""
75
            return response
76

    
77
        if settings.TEST:
78
            if 'TEST-AAI' in request.META:
79
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
80
        else:
81
            #Avoid redirect loops
82
            if request.path.endswith(settings.LOGIN_PATH): 
83
                return
84
            else :
85
                #No authentication info found in headers, redirect to Shibboleth
86
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
87

    
88
    def process_response(self, request, response):
89
        #Tell proxies and other interested parties that the
90
        #request varies based on the auth token, to avoid
91
        #caching of results
92
        response['Vary'] = self.auth_token
93
        return response
94

    
95

    
96
    def _redirect_shib_auth_user(self, user):
97
        response = HttpResponse()
98
        response[self.auth_token] = user.auth_token
99
        response['Location'] = settings.APP_INSTALL_URL
100
        response.status_code = 302
101
        return response