Skip to main content

Authentication viewlet for Zope3

Project description

This package provides an authentication viewlet implementation for Zope3.

Login and logout

Login and logout work both for basic auth and cookie auth.

Setup

The layout page template has to include two content providers (viewlet mangers):

  • login-logout-head inside the head tag to get automatic redirects and JavaScript code which does the logout for basic auth and

  • login-logout inside the body tag to get login and logout links.

The sample template looks like this:

>>> import os.path
>>> template_path = os.path.join(os.path.dirname(__file__), "tests",
...     "login-logout-template.pt")
>>> with open(template_path, "r") as t:
...     print(t.read())
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
    <tal:block replace="structure provider:login-logout-head" />
  </head>
  <body>
    <tal:block replace="structure provider:login-logout" />
    <tal:block replace="structure provider:pagelet" />
  </body>
</html>

This template is registered for the IContainer interface in ftesting.zcml. After creating a container the template is used when browsing the container:

>>> from zope.container.btree import BTreeContainer
>>> layer.getRootFolder()['container'] = BTreeContainer()

Basic auth

When the user is not logged in the login link is displayed:

>>> from zope.testbrowser.wsgi import Browser
>>> skinURL = 'http://localhost/++skin++PageletTestSkin/'
>>> wsgi_app = layer.make_wsgi_app()
>>> browser = Browser(wsgi_app=wsgi_app)
>>> browser.handleErrors = False
>>> browser.open(skinURL + 'container/@@default.html')
>>> browser.url
'http://localhost/++skin++PageletTestSkin/container/@@default.html'
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
  </head>
  <body>
    <a href="http://localhost/++skin++PageletTestSkin/container/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html">Login</a>
  </body>
</html>

Selecting the link leads to the login page, as we use basic auth here, we get an HTTP error 401 (unauthorized):

>>> login_url = browser.getLink('Login').url
>>> browser.raiseHttpErrors = False
>>> browser.getLink('Login').click()
>>> print(browser.headers['status'])
401 Unauthorized
>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html

When adding correct credentials we get authorized:

>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
>>> browser.open(browser.url)

We are redirected to the page where we selected the login link. After logging in the login link is no longer displayed. As we did not specify that logout is supported, no logout link is displayed:

>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/@@default.html
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
  </head>
  <body>
  </body>
</html>

Calling the login URL again leads directly to the page referred in nextURL:

>>> browser.open(login_url)
>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/@@default.html
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
  </head>
  <body>
  </body>
</html>

Calling the login URL again without the query parameter leeds to a confirmation page telling that login was successfull:

>>> browser.open(login_url.split('?')[0])
>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/@@login.html
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
<head>
<title>PageletTestLayout</title>
</head>
<body>
  <div>
   <h1>Login successful!</h1>
   <p style="font-size: 200%"> You are now logged in as <em>Manager</em>. </p>
   <a href=".">Back to the main page.</a>
  </div>
</body>
</html>

Selecting the Back to the main page. link send the user back to the default view of the container. (ftesting.zcml defines @@default.html as the default view.):

>>> browser.getLink('Back to the main page.').click()
>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
  </head>
  <body>
  </body>
</html>

Providing an ILogoutSupported adapter leads to a logout link being displayed:

>>> import zope.component
>>> import zope.interface
>>> import zope.authentication.logout
>>> import zope.authentication.interfaces
>>> zope.component.provideAdapter(
...     zope.authentication.logout.LogoutSupported,
...     adapts=[zope.interface.Interface],
...     provides=zope.authentication.interfaces.ILogoutSupported)
>>> browser.reload()
>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
  </head>
  <body>
    <a href="http://localhost/++skin++PageletTestSkin/container/@@logout.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html">Logout</a>
  </body>
</html>

Logout is done using JavaScript and a redirect. zope.testbrowser >= 5.0 does not follow redirects if they use the meta tag.

As testbrowser is not able to execute JavaScript the user remains authenticated:

>>> logout_url = browser.getLink('Logout').url
>>> browser.getLink('Logout').click()
>>> print(browser.url)
http://localhost/++skin++PageletTestSkin/container/@@logout.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html
>>> print(browser.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
    <script type="text/javascript"><!--
  // clear HTTP Authentication
  ...
  //-->
</script>
<meta http-equiv="refresh"
      content="0;url=http://localhost/++skin++PageletTestSkin/container/@@default.html" />
  </head>
  <body>
    <a href="http://localhost/++skin++PageletTestSkin/container/@@logout.html/@@logout.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40logout.html">Logout</a>
    <div>
  <h1>You are being redirected!</h1>
  <p style="font-size: 150%">
    <a href="http://localhost/++skin++PageletTestSkin/container/@@default.html">
      If you see this screen for more than 5 seconds, click here.
    </a>
  </p>
</div>
  </body>
</html>

Calling the logout URL again after logout (simulated using a new browser instance) leads directly to the page referred in nextURL:

>>> browser2 = Browser(logout_url, wsgi_app=wsgi_app)
>>> print(browser2.url)
http://localhost/++skin++PageletTestSkin/container/@@default.html
>>> print(browser2.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
  </head>
  <body>
    <a href="http://localhost/++skin++PageletTestSkin/container/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40default.html">Login</a>
  </body>
</html>

Calling the logout URL again without the query parameter leeds to a confirmation page telling that logout was successfull:

>>> browser2.open(logout_url.split('?')[0])
>>> print(browser2.url)
http://localhost/++skin++PageletTestSkin/container/@@logout.html
>>> print(browser2.contents)
<!DOCTYPE ...>
<html ...>
  <head>
    <title>PageletTest</title>
    <script type="text/javascript"><!--
  // clear HTTP Authentication
  ...
  //-->
</script>
  </head>
  <body>
    <a href="http://localhost/++skin++PageletTestSkin/container/logout.html/@@login.html?nextURL=http%3A//localhost/%2B%2Bskin%2B%2BPageletTestSkin/container/%40%40logout.html">Login</a>
    <div>
  <h1>Logout successful!</h1>
  <p style="font-size: 200%">
    You are now logged out.
  </p>
  <a href=".">Back to the main page.</a>
</div>
  </body>
</html>

Changes

2.0 (2023-02-09)

  • Add support for Python 3.8, 3.9, 3.10, 3.11.

  • Drop support for Python 2.7, 3.4, 3.5, 3.6.

1.1 (2018-10-18)

  • Add support for Python 3.7.

1.0.1 (2017-06-08)

  • Fix dependencies declared in setup.py.

1.0 (2017-06-07)

  • Update to Python 3. Now supporting: Python 3.4 to 3.6, PyPy2 and PyPy3.

  • Update the tests to zope.testbrowser >= 5.0.

0.8.0 (2010-10-13)

  • Adapted test set up to the changes in z3c.layer.pagelet 1.9 thus requiring at least this version now.

  • Moved code from page template of session credentials login page to view class so it can be customized. (Taken from zope.app.authentication.browser.loginform.LoginForm.) Moved view class SessionCredentialsLoginForm from z3c.authviewlet.auth to z3c.authviewlet.session.

0.7.0 (2009-12-27)

  • Moved files in z3c.authviewlet.browser to z3c.authviewlet as we only have browser code in this package.

  • Broke dependency on zope.app.publisher by defining our own ILogin interface.

0.6.0 (2009-12-24)

  • Added i18n domains to allow translation (done in z3c.locales package).

0.5.0 (2009-11-30)

  • Moved authentication viewlet implementation from z3c.layer.pagelet to this package.

  • Initial release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

z3c.authviewlet-2.0.tar.gz (19.6 kB view hashes)

Uploaded Source

Built Distribution

z3c.authviewlet-2.0-py3-none-any.whl (20.0 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page