LoginRedirect and Login Modules

The LoginRedirect and Login modules provide a "single sign-on" environment for WebStack applications. Unlike the authenticator-only approach, each application or part of an application utilising this mechanism must be wrapped inside a LoginRedirectResource object which determines whether a given transaction contains information identifying the application's user.

How the Modules Work

When a request arrives in the application, the following things happen:

  1. The LoginRedirectResource examines the transaction and attempts to find out whether it identifies a user.
  2. Should sufficient information be present in the transaction, the user is allowed to access the application and is identified in the normal way (ie. the get_user method on the transaction object).
  3. Otherwise, a redirect occurs to a login screen provided by a LoginResource object which then presents a login form to be completed by the user.
  4. The LoginResource object then receives the completed form information and verifies the identity of the user, testing the supplied credentials against the credentials database specified in the deployment of the resource.
  5. Upon successful authentication, the user is redirected back to the application, guarded by LoginRedirectResource which should let the user gain access.

Introducing LoginRedirectResource

The easiest way of introducing LoginRedirectResource objects is to do so in the adapter code, as described in "Writing Adapters". The most significant difference between deploying normal resources and LoginRedirectResource objects is the special way in which such objects are initialised and that they themselves contain the actual resources of the application which provide the real functionality.

Here is what the deployment of LoginRedirectResource objects often looks like:

from WebStack.Resources.LoginRedirect import LoginRedirectResource, LoginRedirectAuthenticator

deploy(
LoginRedirectResource(
login_url="http://localhost:8081",
app_url="http://localhost:8080",
resource=[some resource object which provides the real application behaviour],
authenticator=LoginRedirectAuthenticator(secret_key="horses"),
anonymous_parameter_name="anonymous",
logout_parameter_name="logout"
)
)

Certain parts of the resource are configurable, according to which other services may exist in or alongside the deployed application.

WebStack API - LoginRedirectResource Initialisation

The following parameters must be provided when initialising a LoginRedirectResource object:

login_url
This specifies the location of the separate login application or resource which presents a login screen to unidentified users and logs them in.
app_url
This specifies the location of the application itself - it must therefore be updated according to where the application is eventually deployed.
resource
This provides the resource object which contains the application code, or at least the entry point into various parts of the application code.
authenticator
This provides the authenticator object which decides whether a user is recognised or not. The special LoginRedirectAuthenticator is recommended and must itself be configured using a secret_key parameter which is used to protect user-related information exchanged over the network - the value provided for secret_key must be unguessable and kept secret from unauthorised individuals.
anonymous_parameter_name
An optional parameter providing the name of a request parameter (see "Request Parameters and Uploads") which, if specified, permits a user to access an application without being formally identified. If omitted, all users will be required to identify themselves explicitly.
anonymous_username
An optional parameter providing the name given to anonymous users which is returned when a transaction's get_user method is called. By default, anonymous is used for such users.
logout_parameter_name
An optional parameter providing the name of a request parameter which, if specified, permits a user to log out of an application. If omitted, no means of logging out will be available, although deleting browser cookies will probably have the desired effect.
logout_url
An optional parameter which indicates the location of the resource visited when a user logs out. By default, the location is a path to the root resource in the server environment of the application.
use_logout_redirect
An optional parameter which determines whether users logging out of an application will be redirected to the logout_url or not. By default, users are redirected, but if a false value is given for this parameter, a simple page is presented to the user informing them of the situation - it is recommended that a subclass of LoginRedirectResource be employed should more informative pages be required.
path_encoding
An optional parameter indicating the character encoding used to generate (and, in other places, to interpret) URL-encoded character values in URLs and paths.

See the API documentation for the LoginRedirectResource class for more details.

Redirection from/to the Application

Some server/framework environments do not permit automatic redirection back to the application, notably Apache/mod_python. In such cases, a success screen is presented to the user with a link to the application they were attempting to access.

The Role of Authenticators

In this mechanism, authenticators are employed, but only to verify the credentials of users when LoginResource or LoginRedirectResource objects are accessed. Although it should be possible to reuse application-wide authenticator classes in conjunction with LoginResource, such classes will not provide the additional functionality required to support the "single sign-on" aspects of this mechanism - mixing in such classes with LoginAuthenticator may provide a solution to this issue, however.

Extending LoginRedirectResource

Sometimes, using LoginRedirectResource directly is not appropriate in an application. For example, specifying the app_url and login_url as absolute URLs (so that LoginRedirectResource can redirect users into the application and over to the login screen) may seem like excessive detail which will need to be changed if the application is deployed even in a slightly different location. We might therefore wish to use a PathSelector resource (see "Transaction Attributes" and "Selectors") to record the "root path" into an application and then to employ a login URL which is relative to the "root path".

To achieve this, LoginRedirectResource provides methods which can be overridden - get_app_url and get_login_url - and we might define a subclass of LoginRedirectResource as follows:

class MyLoginRedirectResource(LoginRedirectResource):

"An example of customising LoginRedirectResource."

def get_login_url(self, trans):

"Use a different login URL, using 'trans' to find out what it might be."

# Find out what the PathSelector stored for the root of the application.

root_path = trans.get_attributes()["root"]

# Return the value of the login_url attribute appended to the root path.

return root_path + self.login_url

Since LoginRedirectResource calls the get_login_url method when forming the URL to redirect to the login resource, by overriding the original method from the LoginRedirectResource class we can define different behaviour. Of course, to take advantage of this new behaviour, we must instantiate MyLoginRedirectResource instead of LoginRedirectResource when setting up the application.

Deploying a Login Application

In order for this authentication mechanism to function in its entirety, a login application (or resource) must be available to authenticate unidentified users. It may already be the case that such an application has been deployed and is available at a certain URL - if so, it should be sufficient for a LoginRedirectResource object to be configured as described above, making sure that the login_url actually refers to the location of the existing login application, and that the authenticator object's secret_key is consistent with the way the existing login application has been set up.

However, if no existing login application (or resource) exists, one may be deployed using adapter code similar to the following:

from WebStack.Adapters.BaseHTTPRequestHandler import deploy
from WebStack.Resources.Login import LoginResource, LoginAuthenticator

deploy(
LoginResource( # This is the login application's main resource.
LoginAuthenticator( # This provides authentication support.
secret_key="horses",
credentials=(
("badger", "abc"),
("vole", "xyz"),
)
)
),
address=("", 8081)
)

The above code merely starts a login application in the BaseHTTPRequestHandler environment at a specific address (which corresponds to that specified in the login_url of the LoginRedirectResource used above) and provides a LoginAuthenticator object configured to use a secret_key (which corresponds to the secret_key used in the authenticator of the LoginRedirectResource above) and some user credentials. The user credentials define which users are to be recognised for applications which employ this login application, along with the password details of each user.

WebStack API - LoginAuthenticator Credentials

When initialising a LoginAuthenticator object with credentials, the supplied credentials object must support tests on its contents of the following form:

(username, password) in credentials

In other words, the credentials object must either be a sequence of username and password tuples, or it must implement the __contains__ method and accept such tuples as arguments to that method.

Anonymous Access

With the LoginRedirect and Login modules, it is possible to declare a particular request parameter (see anonymous_parameter_name above) which must be present in the URL used to access a particular application for the client to be given anonymous access. Consequently, anonymous users are then identified specially with a special username that can also be configured (see anonymous_username above).

Logout Functions

With the LoginRedirect and Login modules, it is possible to declare a particular request parameter (see logout_parameter_name above) which must be present in the URL used to access a particular application for the client to be logged out. A special logout confirmation URL may also be configured (see logout_url and use_logout_redirect above).