Statistics
| Branch: | Tag: | Revision:

root / aai / middleware.py @ c06de383

History | View | Annotate | Download (4.8 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
import datetime
8

    
9
class SynnefoAuthMiddleware(object):
10

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

    
15
    def process_request(self, request):
16
        if not request.path.startswith('/api/') :
17
            #print time.strftime("[%d/%b/%Y %H:%M:%S]"), " Path", \
18
            #  request.path , ": Not authenticated"
19
            return
20

    
21
        token = None
22
        #Try to find token in a cookie
23
        try:
24
            token = request.COOKIES['X-Auth-Token']
25
        except Exception:
26
            pass
27

    
28
        #Try to find token in request header
29
        if not token:
30
            token = request.META.get('HTTP_X_AUTH_TOKEN', None)
31

    
32
        if token:
33
            user = None
34
            #Retrieve user from DB or other caching mechanism
35
            try:
36
                user = SynnefoUser.objects.get(auth_token=token)
37
            except SynnefoUser.DoesNotExist:
38
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
39

    
40
            #Check user's auth token
41
            if (time.time() -
42
                time.mktime(user.auth_token_created.timetuple()) -
43
                settings.AUTH_TOKEN_DURATION * 3600) > 0:
44
                #The user's token has expired, re-login
45
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
46

    
47
            request.user = user
48
            return
49

    
50
        #A user authenticated by Shibboleth, must include a uniq id
51
        if Tokens.SIB_EPPN in request.META and Tokens.SIB_SESSION_ID in request.META:
52
            user = None
53
            try:
54
                user = SynnefoUser.objects.get(
55
                    uniq = request.META[Tokens.SIB_EPPN])
56
            except SynnefoUser.DoesNotExist:
57
                pass
58

    
59
            #No user with this id could be found in the database
60
            if user is None:
61
                #Attempt to register the incoming user
62
                if register_shibboleth_user(request.META):
63
                    user = SynnefoUser.objects.get(
64
                        uniq = request.META[Tokens.SIB_EPPN])
65
                    return self._redirect_shib_auth_user(user)
66
                else:
67
                    return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
68

    
69
            #User and authentication token valid, user allowed to proceed
70
            return self._redirect_shib_auth_user(user)
71

    
72
        #An API authentication request
73
        if self.auth_user in request.META and self.auth_key in request.META and 'GET' == request.method:
74
            # This is here merely for compatibility with the Openstack API.
75
            # All normal users should authenticate through Sibbolleth. Admin
76
            # users or other selected users could use this as a bypass
77
            # mechanism
78
            user = SynnefoUser.objects\
79
                    .filter(name = request.META[self.auth_user]) \
80
                    .filter(uniq = request.META[self.auth_key])
81

    
82
            response = HttpResponse()
83
            if user.count() <= 0:
84
                response.status_code = 401
85
            else:
86
                response.status_code = 204
87
                response['X-Auth-Token'] = user[0].auth_token
88
                #TODO: set the following fields when we do have this info
89
                response['X-Server-Management-Url'] = ""
90
                response['X-Storage-Url'] = ""
91
                response['X-CDN-Management-Url'] = ""
92
            return response
93

    
94
        if settings.TEST:
95
            if 'TEST-AAI' in request.META:
96
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
97
        else:
98
            #Avoid redirect loops
99
            if request.path.endswith(settings.LOGIN_PATH): 
100
                return
101
            else :
102
                #No authentication info found in headers, redirect to Shibboleth
103
                return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
104

    
105
    def process_response(self, request, response):
106
        #Tell proxies and other interested parties that the
107
        #request varies based on the auth token, to avoid
108
        #caching of results
109
        response['Vary'] = self.auth_token
110
        return response
111

    
112
    def _redirect_shib_auth_user(self, user):
113
        expire = user.auth_token_created + datetime.timedelta(hours=settings.AUTH_TOKEN_DURATION)
114
        expire_fmt = expire.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
115

    
116
        response = HttpResponse()
117

    
118
        response.set_cookie('X-Auth-Token', value=user.auth_token, expires = expire_fmt, path='/api')
119
        response[self.auth_token] = user.auth_token
120
        response['Location'] = settings.APP_INSTALL_URL
121
        response.status_code = 302
122
        return response