0

I have the following code:

import sys

from zope.interface import implementer

from twisted.python import log
from twisted.internet import reactor
from twisted.web import server, resource, guard
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse


class GuardedResource(resource.Resource):
    """
    A resource which is protected by guard and requires authentication in order
    to access.
    """
    def getChild(self, path, request):
        return self


    def render(self, request):
        return "Authorized!"



@implementer(IRealm)
class SimpleRealm(object):
    """
    A realm which gives out L{GuardedResource} instances for authenticated
    users.
    """

    def requestAvatar(self, avatarId, mind, *interfaces):
        if resource.IResource in interfaces:
            return resource.IResource, GuardedResource(), lambda: None
        raise NotImplementedError()

def main():
    log.startLogging(sys.stdout)
    checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe='blow')]
    portal = Portal(SimpleRealm(), checkers)

    resource = guard.HTTPAuthSessionWrapper(portal, [guard.BasicCredentialFactory('auth')])

    reactor.listenTCP(8889, server.Site(resource = resource))
    reactor.run()

if __name__ == '__main__':
    main()

when we start the server and visit the url: http://localhost:8889/ a prompt pop up and ask us to enter user and password. After entering user = joe and password = blow still we are not authorize to access the website. What is wrong in the code above and how to fix it?

ccpizza
  • 28,968
  • 18
  • 162
  • 169
DTT
  • 39
  • 5
  • I cannot reproduce your behavior. `curl --verbose http://localhost:8889/` receives a 401 response. `curl --verbose http://joe:blow@localhost:8889/` receives a 200 response. – Jean-Paul Calderone Oct 03 '18 at 00:04
  • Strange! I am running `Python 3.6.5` on `Ubuntu 18.04 LTS` with `twisted 18.7.0` and tried `curl --verbose http://joe:blow@localhost:8889/`. However I receives this response: `< HTTP/1.1 401 Unauthorized < Server: TwistedWeb/18.7.0 < Date: Wed, 03 Oct 2018 20:29:49 GMT * Authentication problem. Ignoring this. < WWW-Authenticate: basic realm="auth" < Content-Length: 12 < Content-Type: text/html ` – DTT Oct 03 '18 at 20:31
  • I tested on Python 2.7. Repeating the test on Python 3.6.5, I observe the same behavior as you. Looks like someone failed to port some of Twisted Web to Python 3 properly. You should probably file a ticket in the Twisted tracker. – Jean-Paul Calderone Oct 03 '18 at 21:10
  • thanks Jean-Paul! Could you please provide me also the link to the Twisted tracker? – DTT Oct 03 '18 at 22:07
  • https://twistedmatrix.com/trac – Jean-Paul Calderone Oct 03 '18 at 23:50

1 Answers1

0

So I posted on trac as suggested by @Jean-Paul Calderone and got the problem solved here

There are 2 things to be fixed

  1. render method returns bytes in python3
    def render(self, request):
        return "Authorized!".encode('utf8')
  1. password inside InMemoryUsernamePasswordDatabaseDontUse must be in bytes
    checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe=b'blow')]

So for your code to run in py2 and py3 use this

from __future__ import print_function
import sys
from zope.interface import implementer
from twisted.python import log
from twisted.internet import reactor
from twisted.web import server, resource, guard
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse


class GuardedResource(resource.Resource):
    """
    A resource which is protected by guard and requires authentication in order
    to access.
    """
    def getChild(self, path, request):
        return self


    def render(self, request):
        return "Authorized!".encode('utf8')


@implementer(IRealm)
class SimpleRealm(object):
    """
    A realm which gives out L{GuardedResource} instances for authenticated
    users.
    """

    def requestAvatar(self, avatarId, mind, *interfaces):
        if resource.IResource in interfaces:
            return resource.IResource, GuardedResource(), lambda: None
        raise NotImplementedError()

def main():
    log.startLogging(sys.stdout)
    checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe=b'blow')]
    portal = Portal(SimpleRealm(), checkers)

    resource = guard.HTTPAuthSessionWrapper(portal, [guard.BasicCredentialFactory('auth')])

    reactor.listenTCP(8889, server.Site(resource = resource))
    reactor.run()

if __name__ == '__main__':
    main()
Levon
  • 10,408
  • 4
  • 47
  • 42