No one answered the question below, and I'd still like to get an answer,
but in the meantime I got CookieAuthenticator to work by overriding
challenge(Response, boolean) as follows.
@Override public void challenge(Response response, boolean stale) {
response.redirectSeeOther(
new Reference(getLoginFormPath())
.addQueryParameter(
getRedirectQueryName(),
response.getRequest().getResourceRef().toString()
)
.toString() // Interpret URI relative to this host.
);
}
This would seem to be a good candidate for a default implementation of
CookieAuthenticator.challenge(Response, boolean).
Here's the rest of the story: I have an AuthApplication to which /auth
requests are routed in my main component.
// MainComponent initialization:
host.attach("/auth", authApplication);
That application routes /loginForm to a login form resource and routes
everything else to an instance of my CookieAuthenticator extension around a
Restlet that does nothing. (If you leave out this vacuous Restlet, the
machinery complains about a Filter with no target.)
// In AuthApplication.createInboundRoot:
Authenticator authenticator = ... my CookieAuthenticator extension ...;
authenticator.setNext(new Restlet() {
@Override public void handle(Request request, Response response) {
getLogger().debug("Null restlet");
}
});
router.attach("/loginForm", LoginFormServerResource.class);
router.attachDefault(authenticator);
LoginFormServerResource is a straighforward use of Freemarker's
TemplateRepresentation:
@Get public Representation showLoginForm() {
ImmutableMap<String, String> dataModel = ImmutableMap.of(
"targetUri", getQuery().getFirstValue("targetUri")
);
return new TemplateRepresentation(
LOGIN_FORM_TEMPLATE, freemarkerConfiguration,
dataModel, MediaType.TEXT_HTML
);
}
The template has a form element with an action to post to the login
resource, using the default values of CookieAuthenticator's
identifierFormName and secretFormName properties ("login", "password"). A
stripped-down example:
<form action="/auth/login?targetUri=${targetUri}" method="POST">
<input type="text" id="login" name="login" size="15" />
<input type="password" id="password" name="password" size="15" />
<input type="submit" value="Login" />
</form>
Because I've made authentication/authorization a separate Application, I
had to set the cookie path to "/" in my CookieAuthenticator extension in
order to have the credentials in the cookie apply to the entire URI-space
of my Restlet Component.
@Override protected CookieSetting getCredentialsCookie(Request request,
Response response) {
CookieSetting credentialsCookie =
super.getCredentialsCookie(request, response);
credentialsCookie.setPath("/");
return credentialsCookie;
}
--tim
On Mon, Dec 3, 2012 at 3:38 PM, Tim Peierls <[email protected]> wrote:
> The class javadoc for CookieAuthenticator says:
>
> When the credentials are missing or stale, the challenge(Response,
>> boolean)<http://www.restlet.org/documentation/2.1/jee/ext/org/restlet/ext/crypto/CookieAuthenticator.html#challenge(org.restlet.Response,%20boolean)>
>> method
>> is invoked by the parent class, and its default behavior is to redirect the
>> user's browser to the
>> getLoginFormPath()<http://www.restlet.org/documentation/2.1/jee/ext/org/restlet/ext/crypto/CookieAuthenticator.html#getLoginFormPath()>
>> URI,
>> adding the URI of the target resource as a query parameter of name
>> getRedirectQueryName()<http://www.restlet.org/documentation/2.1/jee/ext/org/restlet/ext/crypto/CookieAuthenticator.html#getRedirectQueryName()>
>> .
>
>
> But the javadoc for CookieAuthenticator.challenge(Response, boolean) says
> it must be overridden to return a login form representation, and in fact
> the implementation of challenge(Response, boolean) is to call
> super.challenge(response, stale), in both stable and unstable versions. The
> supertype version (ChallengeAuthenticator.challenge) sets the status to
> unauthorized and creates a challenge request from the challenge scheme and
> puts it in the response. This fails because the HTTP_Cookie scheme is not
> meant to be used in this way.
>
> My question is whether the class comment is the intent, and the current
> implementation of CookieAuthenticator.challenge is incomplete, or if the
> class comment is out of date. If the latter is the case, then can someone
> give an example of how to override challenge?
>
> --tim
>
------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=3034308