clubby789
clubby789

Reputation: 2723

CherryPy authentication timeout

I added digest authentication to my CherryPy server, and I wanted to know on what criteria the users' authentication is revoked and they are prompted to enter credentials again. Deleting cookies doesn't force a prompt, but using Incognito or another browser does.

My config:

{ 'tools.auth_digest.on': True,
  'tools.auth_digest.realm': 'localhost',
  'tools.auth_digest.get_ha1': auth_digest.get_ha1_dict_plain(USERS),
  'tools.auth_digest.key': key,
  'tools.auth_digest.accept_charset': 'UTF-8' }

Thanks

Upvotes: 1

Views: 324

Answers (1)

cyraxjoe
cyraxjoe

Reputation: 5741

You need to have the proper HTTP response so that the browser clear out the user credentials, basically responding with 401 Unauthorized and a challenge in how to authenticate with the WWW-Authenticate header.

Here is an implementation using a custom CherryPy tool and a Cookie that is used as way to communicate the intention to the browser and the backend (HTTP auth is stateless and we have to go back and forth to deauth and redirect).

import cherrypy
from cherrypy.lib import auth_digest


REALM = 'localhost'
KEY = '24684651368351320asd1wdasd'
CHARSET = 'UTF-8'


@cherrypy.tools.register('before_handler')
def with_logout_handler():
    if cherrypy.request.cookie.get('Unauthorize') is not None:
        response = cherrypy.response
        response.headers['WWW-Authenticate'] = auth_digest.www_authenticate(
            realm=REALM,
            key=KEY,
            accept_charset=CHARSET
        )
        # delete the cookie that was used to mark the intention to logout
        response.cookie['Unauthorize'] = 1
        response.cookie['Unauthorize']['expires'] = 0
        raise cherrypy.HTTPError(
            401, 'You are not authorized to access that resource')


class App:
    @cherrypy.expose
    @cherrypy.tools.with_logout_handler()
    def index(self):
        return ('Welcome {}! Do you want to <a href="/logout">logout</a>?'
                .format(cherrypy.request.login))

    @cherrypy.expose
    def logout(self):
        """
        Set a cookie to give it a clue to the index method to
        remove the user credentials from the following requests.

        This will be handled by the tool `with_logout_handler`.
        """
        cherrypy.response.cookie['Unauthorize'] = 1
        raise cherrypy.HTTPRedirect("/")


def main():
    users = {
        'foo': 'bar'
    }
    cherrypy.quickstart(App(), config={
        '/': {
            'tools.auth_digest.on': True,
            'tools.auth_digest.realm': REALM,
            'tools.auth_digest.get_ha1': auth_digest.get_ha1_dict_plain(users),
            'tools.auth_digest.key': KEY,
            'tools.auth_digest.accept_charset': CHARSET
        },
    })

if __name__ == '__main__':
    main()

Upvotes: 2

Related Questions