header image

Integrating CAS and Wicket

November 24, 2009, add a comment

At AirlineSim we use CAS for user authentication and right now we are in the process of migrating parts of the game to the great web framework Wicket. Yesterday I thought about a way of integrating both in a way that a user is automatically redirected to a login page when he lacks access rights and that he returns to the exact same page after he has completed the login. All should be done in a "Wicket way". Below you find my approach, please let me know when you find errors or if you can think of ways so solve it in a better way. For demonstration purposes I use simplified code passages. It looks slighty more complex in AirlineSim.

The first step is to check in a custom PageAuthorizationStrategy whether a CAS assertion exists. I'm using the filters provided by the Jasig CAS Client to place the assertion in an AssertionHolder. If no assertion is provided (which means the user is not logged in) I use Wicket's intercept page mechanism to redirect the user to CAS.

 1 public class CASPageAuthorizationStrategy
 2 		extends AbstractPageAuthorizationStrategy
 3 {
 4 	@Override
 5 	protected <T extends Page> boolean isPageAuthorized(Class pageClass)
 6 	{
 7 		Assertion assertion = AssertionHolder.getAssertion();
 8 		if (assertion == null && isLoginRequired(pageClass))
 9 		{
10 			StringBuffer url = new StringBuffer();
11 			url.append("https://your.cas.installation/login?service=");
12 			try
13 			{
14 				url.append(URLEncoder.encode(
15 					"http://your.cas.clientapp/app/redirectAfterLogin", "UTF-8"));
16 			}
17 			catch (UnsupportedEncodingException e)
18 			{
19 				e.printStackTrace();
20 			}
21 			RedirectPage intercept = new RedirectPage(url);
22 			throw new RestartResponseAtInterceptPageException(intercept);
23 		}
24 		return true;
25 	}
26 }

As you can see, the code is pretty much straight forward: When the user isn't logged in and a login is required ("isLoginRequired" just for demonstration purposes), the URL for the redirect to CAS is built. Since I'm using an intercept page, the path in the service parameter always points to "/redirectAfterLogin", but more about that in a minute. The URL is passed to a new instance of RedirectPage which itself is passed to the RestartResponseAtInterceptPageException. When this exception is thrown, Wicket will "remember" the page the user just tried to call and redirect him to the RedirectPage. The latter will immediately redirect him to CAS for login.

So what about the "/redirectAfterLogin" in the service path? At this location I mounted the following page class:

 1 public class RedirectAfterLoginPage
 2 		extends WebPage
 3 {
 4 	public RedirectAfterLoginPage()
 5 	{
 6 		super();
 7 		if (!continueToOriginalDestination())
 8 			setResponsePage(getApplication().getHomePage());
 9 	}
10 }

Its job is very simple. All it does is redirecting the user to the page Wicket "remembered" when the RestartResponseAtInterceptPageException was thrown. Since the user might access this page by accident and there is no markup for it, make sure to provide a response page even if no original destination is available. Otherwise the user will get to see an error page. I used the application's home page as the default here.

And that's basically it. Please note that the code snippets above are untested pseude code and will most definitely have to be adjusted to your environment.


comments powered by Disqus