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

Reply via email to