Skip to content

Instantly share code, notes, and snippets.

@minskmaz
Last active July 13, 2018 00:06
Show Gist options
  • Save minskmaz/ab218d7b137b24ede8ffc7e3ea6e2392 to your computer and use it in GitHub Desktop.
Save minskmaz/ab218d7b137b24ede8ffc7e3ea6e2392 to your computer and use it in GitHub Desktop.
class PasswordCredentialChecker(object):
implements(ICredentialsChecker)
credentialInterfaces = (IUsernamePassword,)
def __init__(self):
print("INSTANTIATED PasswordCredentialChecker")
self.crud = getUtility(ITraceCrud, 'trace_crud')()
self.db = getUtility(ITwistarConnectionPool, 'twistar')
def requestAvatarId(self, credentials):
def process(matched):
if len(matched) == 1:
if matched[0][2] == credentials.password:
print "MATCHING PASSWORDS"
print credentials.username
return defer.succeed(credentials.username)#succeed(credentials.username)
else:
return fail(credError.UnauthorizedLogin("Bad password"))
else:
return fail(credError.UnauthorizedLogin("No such user"))
username = credentials.username
if username:
stmnt = "SELECT * FROM Principal WHERE username = '{}'".format(username)
d = self.db().Registry.DBPOOL.runQuery(stmnt)
d.addCallback(process)
return d # <----- this fixed it!
checkers.PasswordCredentialChecker = PasswordCredentialChecker
class WebAuthenticatedRealm(object):
interface.implements(IRealm)
def __init__(self, anonymousRoot, authorizedRoot):
self.anonymousRoot = anonymousRoot
self.authorizedRoot = authorizedRoot
def requestAvatar(self, avatarId, request, *interfaces):
"""
Called after the user has successfully authenticated, returning an
IResource instance representing the user's HTTP interface to an app.
"""
print "####################################################"
##### HERE'S WHERE IT BREAKS DOWN, avatarId comes is as None
print "requestAvatar", avatarId, request, interfaces
print "####################################################"
if resource.IResource in interfaces:
if not avatarId:
return (
resource.IResource,
self.anonymousRoot(),
logout)
else:
avatar = self.authorizedRoot()
session = request.getSession()
session.avatar = avatar
if not session.expireCallbacks:
session.notifyOnExpire(lambda: sessionExpired(session))
return (
resource.IResource,
avatar,
logout
)
log.msg('requestAvatar: Realm not implemented.')
raise NotImplementedError()
class WebAuthSessionWrapper(resource.Resource):
"""
Wrap a twisted.cred.portal, requiring authN/authZ via various providers.
"""
isLeaf = False
def __init__(self, portal, credentialFactories, *children):
"""
Initialize a session wrapper.
"""
resource.Resource.__init__(self)
self._portal = portal
self._credentialFactories = credentialFactories
for path, child in children:
self.putChild(path, child)
def _authorizedResource(self, request):
"""
Get the twisted.web.resource.IResource which the given request is
authorized to receive. If the proper credentials are present, the
resource will be requested from the portal.
"""
authProvider = None
session = request.getSession()
if session.avatar is not None:
return session.avatar
else:
userCredentials = credentials.Anonymous()
if request.method == 'POST':
authProvider = request.args['scheme'][0]
for credentialFactory in self._credentialFactories:
if credentialFactory.scheme == authProvider:
userCredentials = credentialFactory.decode(request)
break
return DeferredResource(self._login(userCredentials, request))
def _login(self, credentials, request):
"""
Get the twisted.web.resource.IResource avatar for the given credentials.
Returns a twisted.internet.defer.Deferred which will be called back with
a twisted.web.resource.IResource avatar or which will errback if
authentication fails.
"""
d = self._portal.login(credentials, request, resource.IResource)
d.addCallbacks(self._loginSucceeded, self._loginFailed)
return d
def _loginSucceeded(self, (interface, avatar, logout)):
#print "_loginSucceeded", interface, avatar, logout
return avatar
def _loginFailed(self, result):
"""
Handle login failure by presenting either another challenge (for
expected authentication/authorization-related failures) or a server
error page (for anything else).
"""
errorMessage = result.getErrorMessage()
if result.check(credError.Unauthorized, credError.LoginFailed):
log.msg('txsocmob.cred.HTTPSessionWrapper._loginFailed: ' + errorMessage)
return Redirect('/')
else:
return resource.ErrorPage(500, 'Server error.', errorMessage)
def getChild(self, path, request):
"""
TBD.
"""
# Don't consume any segments of the request - this class should be
# transparent!
log.msg('getChild: ' + path)
request.postpath.insert(0, request.prepath.pop())
return self._authorizedResource(request)
@ldanielburr
Copy link

ldanielburr commented Jul 12, 2018

Doesn't look like you ever return the Deferred you created on https://gist.github.com/minskmaz/ab218d7b137b24ede8ffc7e3ea6e2392#file-credentialchecker-py-L26. I'd say that's your problem, but I haven't done twisted cred stuff in a while.

To clarify, you are returning None, when you should be returning the Deferred. Hope this helps!

@minskmaz
Copy link
Author

That did the trick - thanks again @ldanielburr !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment