dev@glassfish.java.net

Re: Strange form authentification behaviour

From: Ron Monzillo <Ronald.Monzillo_at_Sun.COM>
Date: Thu, 13 Dec 2007 13:28:58 -0500

Jan,

thanks for the explanation.

If I undersatnd correctly, a request uri always saved. when someone
accesses the login page directly and the saved uri is not protected, the
authenticator will not be called to match the request and the
authentication state (that is stored in the session) is unrecognizable
without further processing by the authenticator (including request
matching). As such it will not be applied to subsequent requests.

when the authenticator knows that that the redirection will not result
in the authenticator being recalled to match the saved request (because
the saved uri is not protected), then the authenticator will need to do
the registration, or the effects of the authentication will be lost.

Ron

Roman Pokhodzhay wrote:
> 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
>
>
>
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net