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.
When a request arrives in the application, the following things happen:
LoginRedirectResource
examines the transaction
and attempts to find out whether it identifies a user.get_user
method on the transaction
object).LoginResource
object which then presents a login form to be completed by the user.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.LoginRedirectResource
which
should let the user gain access.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.
The following parameters must be provided when initialising a
LoginRedirectResource
object:
login_url
app_url
resource
authenticator
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
anonymous_username
get_user
method is
called. By default, anonymous
is used for such users.logout_parameter_name
logout_url
use_logout_redirect
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
See the API documentation for the LoginRedirectResource
class for more details.
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.
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.
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.
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.
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.
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).
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).