How to Use Basic Unified Login

Draft 0.4
Jan 8, 2001
Ted Lee (tlee@startups.com)
 

1. Applicability

Read this document when any of the following are true:

If this document doesn't meet your needs, you may want to look at:

Background

There are certain sections of our site which require a user to log in prior to accessing the page.  In order to log in, a user must provide a username and a password.  Users may obtain usernames and passwords in several areas on the site.  For instance, it is possible to sign up as a registered client to obtain a username and password, or one can sign up as a service provider to obtain a username and password.  It is undesirable to require a user to obtain separate usernames and passwords to access each section of our site, so instead we introduce the concept of roles.

A user role is added to a user when the user signs up for a particular section of the site.  For example, a new user signing up as a client will obtain a username, a password, and internally will be assigned a client role.  Roles may be added to existing username/password pairs if the user signs up for other sections of the site.  For example, a user who is already a client may sign up as a service provider; in this case, the user would have a single username and password but would have two roles assigned to her--client role and service provider role.

Certain sections of the site require the user have a particular role in addition to being logged in.  Some pages require not only the presence of a particular role but also the presence of certain permissions within that role.

The desired effect of using unified login is that when a user tries to access a page which requires login, a login screen will appear.  If the login is successful and the user has the appropriate roles and permissions required for that page, the user will be able to access the page.  A flowchart of the desired behavior is shown below:

There may be some situations where you wish to handle your own login flow--for example, if you want a static login page that the user always goes through regardless of whether or not the user has already logged in.  If this is the case, please read How To Create Static Login Pages.

2. Steps for Using Unified Login

In order to require login to access a page, you need to override one or more methods in the Model object.  If you don't know what a Model object is, please see How To Create Web Pages With Forms (Java Developer)Model defines a number of methods that can be usefully overridden to change access protection behavior: These methods will be explained in more detail below.

2.1 Specify what role is required to access a given page

Model defines a method called getRequiredRole() which returns a Class object.  By default it returns null.  Override this method to return the Class object for the role that is required to access the page.  For example, if JobBoardRole is required to access the page, you would implement the method like this:

public Class getRequiredRole() {
    return JobBoardRole.class;
}

Note that in order for the role to be checked, the user must be logged in.  In effect, specifying a required role always specifies that the user must be logged in.

2.2 Specify the Login Page Text and Title

By default, a generic login page will appear if the framework determines that the user does not have the required role.  If you wish the login page to say something specific, like "In order to access the Job Connection, please log in", you must override the getLoginPageMessage() method.  You may also specify the title of the page by overriding getLoginPageTitle():

public String getLoginPageMessage() {
    return "In order to access the Second Page you must first log in.";
}

public String getLoginPageTitle() {
    return "Log in to Second Page";
}

2.3 Specify the success URL

If the user successfully logs in and has the required role, by default the user is sent to the page they were originally trying to access.  If this behavior is adequate, go on to the next step.  In some cases, it may be desirable to send the user to a specific page rather than the page they tried to access.  For example, if the user tries to enter step 3 of a 5 page application by typing in the URL for page 3 in their browser, we might want to send them to step 1 regardless of the fact that they were trying to go to step 3.  For example,

public String getAccessSuccessfulURL() {
    return "/jobboard/index.jsp";
}

2.4 Specify the permission denied URL

It is possible to have a user log in successfully but not have the role required to access a page, or if they have the role they may not have the required permission.  In this situation, the user should be sent to a different page.  Typically it would be a signup page.  For example:

public String getPermissionDeniedURL() {
    return "/jobboard/freeposting/SingleFreePosting.jsp";
}

By default, the behavior is to show a page the just lists the roles that the user has:


In most situations this is not the desired behavior, so it will usually be the case that the getPermissionDeniedURL() should be overridden.

Tip:

If you have many pages with the same access protection, create an abstract subclass of Model, override the methods discussed above, and extend the subclass instead of Model for individual pages.  For example:


 

2.5 Add an Access Check Into the JSP View

In the jsp file corresponding to the Model that you just modified, add a little jsp scriptlet just after the usebean declaration.  For example:

<jsp:useBean id="thirdPageModel" class="com.startups.testunifiedlogin.ThirdPageModel"
scope="session" create="yes"/>
<%
thirdPageModel.checkAccess(request, response);
%>

This scriptlet turns on all of the access checking that you added to the Model for the page.

3.  Design Discussion

The goal of the unified login framework is to support the following behavior: We have chosen to make the implementors of Model objects (from the MVC pattern) responsible for adding access permissions to the page models.  We could have made a centralized lookup table of permissions and pages, but someone would have to maintain it and we would have needed a separate maintenance application.  It seems reasonable that the implementor of a page and its logic should know what permissions are necessary to access that page.  The drawback is that changing the permissions for a page requires a recompile.

Role object granularity

Multiple roles vs multiple permissions in a single role.  Most of the time it seems as though multiple permissions in a role is overkill and confusing--when do you decide to make a permission vs another role?  However, one clear case where it seems that permissions would be useful is in admin roles.  We could go crazy with permissions hierarchies but we chose to go with simple string permissions.  We've decided to not initially offer individual permissions in roles but we've left the door open for extension by allowing people to override isAccessibleTo() with a version that checks additional things.  More information on this is available in the document "How to Specify And Use Role Permissions".

Known Problems

4 Version History

0.4, Jan 8, 2000.  Added link to and explanation for  "How To Create Static Login Pages".
0.3, Dec 22, 2000.  Added required jsp additions, removed need for use of overloaded enterState() method.  Added getLoginFailedURL().
0.2, Dec 15, 2000.  Broke off Role Permissions into separate document.  Added isAccessibleTo() method to Model.
0.1 First Version