1 # Copyright (c) 2008 by Florian Friesdorf
3 # GNU Affero General Public License (AGPL)
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as
7 # published by the Free Software Foundation; either version 3 of the
8 # License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
15 # You should have received a copy of the GNU Affero General Public
16 # License along with this program. If not, see
17 # <http://www.gnu.org/licenses/>.
20 __author__
= "Florian Friesdorf <flo@chaoflow.net>"
21 __docformat__
= "plaintext"
23 # this should be moved from zope.app.authentication to zope.authentication
24 from zope
.app
.authentication
.interfaces
import ICredentialsPlugin
25 from zope
.app
.authentication
.principalfolder
import PrincipalInfo
27 from zope
.app
.container
.contained
import Contained
28 from zope
.interface
import implements
, alsoProvides
29 from zope
.component
import getUtility
30 from zope
.publisher
.interfaces
import IRequest
32 from paula
.authentication
.interfaces
import IAuthProviders
33 from paula
.authentication
.interfaces
import IAuthenticatorPlugin
34 from paula
.authentication
.interfaces
import ILocalAuthenticatorPlugin
35 from paula
.authentication
.interfaces
import ICredentialsFromMappingPlugin
38 class AuthenticatorPlugin(object):
39 """Authenticate users with auth providers from an IAuthProviders
41 May be registered globally, as only functionality is implemented.
44 >>> apu = UserDict.UserDict()
45 >>> alsoProvides(apu, IAuthProviders)
46 >>> provideUtility(apu)
50 ... validate = lambda login=None,password=None: \\
51 ... password == 'correct',
56 >>> ap = AuthenticatorPlugin()
58 >>> p = ap.authenticateCredentials(None)
65 >>> p = ap.authenticateCredentials(credentials)
70 ... 'password': 'correct',
72 >>> p = ap.authenticateCredentials(credentials)
78 ... 'password': 'correct',
80 >>> p = ap.authenticateCredentials(credentials)
84 >>> credentials['login'] = 'login'
85 >>> p = ap.authenticateCredentials(credentials)
86 >>> from zope.app.authentication.interfaces import IPrincipalInfo
87 >>> IPrincipalInfo.providedBy(p)
92 >>> credentials['password'] = 'wrong'
93 >>> p = ap.authenticateCredentials(credentials)
97 implements(IAuthenticatorPlugin
)
102 return getUtility(IAuthProviders
)
104 def authenticateCredentials(self
, creds
):
106 if not (creds
.has_key('login') and creds
.has_key('password')):
108 except AttributeError:
111 # retrieve auth provider utility
115 # retrieve auth provider for principal
120 # use authprovider to verify credentials
121 if not ap
.validate(login
=creds
['login'],password
=creds
['password']):
125 title
= description
= u
""
126 return PrincipalInfo( id, login
, title
, description
)
128 def principalInfo(self
, id):
133 title
= description
= u
""
134 return PrincipalInfo( id, login
, title
, description
)
137 class LocalAuthenticatorPlugin(
141 """XXX: still not sure whether this could be the same as AP
143 implements(ILocalAuthenticatorPlugin
)
146 # """when doing this in the version above, I am getting a
147 # ComponentLookupError...
149 # return getUtility(IAuthProviders, context=getSite())
152 class CredentialsFromMappingPlugin(Contained
):
153 """Just returns a mapping it is passed
155 Useful, if you use paula and PAU just for authentication but not for
156 challenging, i.e./e.g. from PlonePAS you already get the credentials in a
157 mapping and don't need to bother with challenging.
159 May be registered globally, as only functionality is implemented.
161 >>> cp = CredentialsFromMappingPlugin()
163 >>> c = cp.extractCredentials(m)
166 >>> IRequest.providedBy(m)
169 implements(ICredentialsFromMappingPlugin
)
171 def extractCredentials(self
, mapping
):
174 # tune the mapping, PAU needs an IRequest to find its factories
175 # If this does not work, better let the AttributeError go here, than
176 # later in the getMultiAdapter lookup of PAU
177 if not IRequest
.providedBy(mapping
):
178 alsoProvides(mapping
, IRequest
)
182 def challenge(self
, request
):
183 pass # challenge is a no-op for this plugin
185 def logout(self
, request
):
186 pass # logout is a no-op for this plugin