1
# -*- test-case-name: twisted.web2.test.test_httpauth -*-
4
Wrapper Resources for rfc2617 HTTP Auth.
6
from zope.interface import implements
7
from twisted.cred import error
9
from twisted.web2 import resource
10
from twisted.web2 import responsecode
11
from twisted.web2 import http
12
from twisted.web2 import iweb
14
class UnauthorizedResponse(http.StatusResponse):
15
"""A specialized response class for generating www-authenticate headers
16
from the given L{CredentialFactory} instances
19
def __init__(self, factories, remoteAddr=None):
20
super(UnauthorizedResponse, self).__init__(
21
responsecode.UNAUTHORIZED,
22
"You are not authorized to access this resource.")
25
for factory in factories.itervalues():
26
authHeaders.append((factory.scheme,
27
factory.getChallenge(remoteAddr)))
29
self.headers.setHeader('www-authenticate', authHeaders)
32
class UnauthorizedResource(resource.LeafResource):
33
"""Returned by locateChild or render to generate an http Unauthorized
37
def __init__(self, factories):
39
@param factories: sequence of ICredentialFactory implementations
40
for which to generate a WWW-Authenticate header.
42
self.factories = factories
44
def render(self, req):
45
return UnauthorizedResponse(self.factories, req.remoteAddr)
48
class HTTPAuthResource(object):
49
"""I wrap a resource to prevent it being accessed unless the authentication
50
can be completed using the credential factory, portal, and interfaces
54
implements(iweb.IResource)
56
def __init__(self, wrappedResource, credentialFactories,
59
@param wrappedResource: A L{twisted.web2.iweb.IResource} to be returned
60
from locateChild and render upon successful
63
@param credentialFactories: A list of instances that implement
64
L{ICredentialFactory}.
65
@type credentialFactories: L{list}
67
@param portal: Portal to handle logins for this resource.
68
@type portal: L{twisted.cred.portal.Portal}
70
@param interfaces: the interfaces that are allowed to log in via the
72
@type interfaces: L{tuple}
75
self.wrappedResource = wrappedResource
77
self.credentialFactories = dict([(factory.scheme, factory)
78
for factory in credentialFactories])
80
self.interfaces = interfaces
82
def login(self, factory, response, req):
83
def _loginSucceeded(res):
84
return self.wrappedResource
86
def _loginFailed(res):
87
return UnauthorizedResource(self.credentialFactories)
90
creds = factory.decode(response, req)
91
except error.LoginFailed:
92
return UnauthorizedResource(self.credentialFactories)
94
return self.portal.login(creds, None, *self.interfaces
95
).addCallbacks(_loginSucceeded,
98
def authenticate(self, req):
99
authHeader = req.headers.getHeader('authorization')
101
if authHeader is None or authHeader[0] not in self.credentialFactories:
102
return UnauthorizedResource(self.credentialFactories)
104
return self.login(self.credentialFactories[authHeader[0]],
107
def locateChild(self, req, seg):
108
return self.authenticate(req), seg[1:]
110
def renderHTTP(self, req):
111
return self.authenticate(req)