dev@glassfish.java.net

RE: Re: Strange form authentification behaviour

From: Roman Pokhodzhay <Roman_Pokhodzhay_at_epam.com>
Date: Thu, 13 Dec 2007 10:28:12 +0200

Hi Ron, Jan
 
It seems fix for https://glassfish.dev.java.net/issues/show_bug.cgi?id=1933 <https://glassfish.dev.java.net/issues/show_bug.cgi?id=1933> should help, but as for me in some strange manner. Why you can simply register user when authentification passed (you can put register method call after auth passed), and why user should be registered when he/she only requests protected resource but not direct requets to login page? Currently such method is called only within "if (matchRequest(request)) {" block.
(FormAuthenticator.java).
For example BasicAuthenticator do it after successful realm authentication:
 
if (authorization != null) {
 String username = parseUsername(authorization);
 String password = parsePassword(authorization);
 principal = context.getRealm().authenticate(username, password);
 if (principal != null) {
     register(request, response, principal, Constants.BASIC_METHOD,username, password);
    String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
     if (ssoId != null) {
       getSession(request, true);
      }
    return (true);
   }
}

________________________________

From: Jan.Luehe_at_Sun.COM [mailto:Jan.Luehe_at_Sun.COM]
Sent: Чт 13.12.2007 3:02
To: dev_at_glassfish.dev.java.net
Subject: Re: Strange form authentification behaviour



Hi Ron,

Ron Monzillo wrote:

>>
>>
>> Hello!
>>
>> I can’t retrieve currently logged in user from request (When I go to
>> the login page directly and login via form base method). It happens
>> because method /authenticate// /in
>> /org.apache.catalina.authenticator//.//FormAuthenticator// /doesn’t
>> call method /register//(/org.apache.catalina.authenticator.
>> AuthenticatorBase/)/ which save principal in request.
>>
>> But FormAuthenticator do it only in case when resource is secure and
>> if the re-submit happens of the original request URI.
>>
>>
>>
>> Is this standart behavior?
>>
> Roman,
>
> I think this is a bug (which, fwiw, appears to have been around for
> some time). Thanks for bringing it to our attention.
>
> Have you tested, or can you suggest a fix?
>
> It looks to me like maybe the following block from
> FormAuthenticator.authenticate should be changed to call register, and
> maybe it need not call saveRequest when the current request contains
> the loginAction.
>
> requestURI = savedRequestURL(session);
> if (requestURI == null) {
> // requestURI will be null if the login form is submitted
> // directly, i.e., if there has not been any original request
> // that was stored away before the redirect to the login form was
> // issued. In this case, assume that the original request has been
> // for the context root, and have the welcome page mechanism take
> // care of it
> requestURI = hreq.getContextPath() + "/";
> saveRequest(requestURI, hreq.getMethod(), session);
> }


the above code was added in an effort to fix:

https://glassfish.dev.java.net/issues/show_bug.cgi?id=1933
("Admin login screen gives "Error Accessing Page:" error after logging in")

Assume the FORM's login page was accessed directly, so the first
invocation of FormAuthenticator.authenticate() will authenticate the
user, store the autenticated principal in the session:

session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);

and then attempt to restore the original request URI (which prompted
authentication in the first place) and redirect to it:

// Redirect the user to the original request URI (which will cause
// the original request to be restored)
requestURI = savedRequestURL(session);
if (requestURI == null) {
// requestURI will be null if the login form is submitted
// directly, i.e., if there has not been any original request
// that was stored away before the redirect to the login form was
// issued. In this case, assume that the original request has been
// for the context root, and have the welcome page mechanism take
// care of it
requestURI = hreq.getContextPath() + "/";
saveRequest(requestURI, hreq.getMethod(), session);
}
.
If the login page was accessed directly, "requestURI" will be null (there
is nothing to restore in this case), so what the above code does is to
pretend
that the original request was for "<context_root>/". This "requestURI"
is then
saved in the session, using saveRequest() (see further down for why calling
saveRequest() is necessary in this case).

The request is then redirected to the restored "requestURI", which in this
case will be equal to "<context_root>/":

hres.sendRedirect(hres.encodeRedirectURL(requestURI));

This will trigger another invocation of FormAuthenticator.authenticate()
down
the line, but this time, matchRequest() will return true (this is why
the above
code had to call saveRequest(), since matchRequest() matches the redirected
request against whatever was saved):

if (matchRequest(request)) {

Since matchRequest() will return true, the principal is retrieved from
the session, and register() is called:

session = getSession(request, true);
principal = (Principal)
session.getNote(Constants.FORM_PRINCIPAL_NOTE);
register(request, response, principal, Constants.FORM_METHOD,
(String) session.getNote(Constants.SESS_USERNAME_NOTE),
(String) session.getNote(Constants.SESS_PASSWORD_NOTE));

So from what I can tell, the existing code is correct, i.e., it is
necessary to call
saveRequest() if the login page was accessed directly, and
FormAuthenticator.register()
will still be called.

Let me know if I missed anything.

Thanks,


Jan


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
For additional commands, e-mail: dev-help_at_glassfish.dev.java.net