You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Scott Kelley <sk...@biomail.ucsd.edu> on 2003/06/11 20:13:52 UTC
Valve as Custom Authenticator
We've had an Apache/Tomcat configuration deployed for a couple years
now. Authentication is handled by a custom Apache plugin written in
C. Everything works great and has been quite reliable.
Now we would like to move to a standalone Tomcat configuration and
have been investigating writing a Valve/Authenticator to replace our
existing Apache plugin.
I've written a prototype Valve and it does almost everything we need.
This gives us the ability to require a server-wide login independent
of how the individual servlet contexts are configured. This ends up
being Tomcat-specific, but we're ok with that.
The only problem with the current prototype is that if a user hits a
servlet or JSP in a Context that's configured for basic
authentication, they still get the browser-generated basic login
dialog, even after being logged in with our Valve.
In my code, I check for a particular cookie, and if I find it, I set
the user principal in the request to the appropriate user, something
like this:
// Has connection already been authenticated
// (i.e. do we have the login cookie?)
Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
// If the request has the login cookie, let it pass through
if (lcookie!=null) {
log("Found login cookie, validating");
if (validLoginCookie(lcookie,hreq)) {
log("cookie is valid, allowing request");
// See AuthenticatorBase.invoke(), which also sets
authType and userPrincipal
// See SignleSignOn.invoke(), which also set authType and
userPrincipal
hrequest.getRequest().setUserPrincipal(new
TempPrincipal("bob_temp_user"));
hrequest.getRequest().setAuthType("BASIC");
context.invokeNext(request,response);
} else {
log("cookie not valid, going to error page");
hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
}
return;
}
I had thought that this would work, because later in the pipeline the
request hits BasicAuthenticator, which does this:
public boolean authenticate(HttpRequest request,
HttpResponse response,
LoginConfig config)
throws IOException {
// Have we already authenticated someone?
Principal principal =
((HttpServletRequest) request.getRequest()).getUserPrincipal();
if (principal != null) {
if (debug >= 1)
log("Already authenticated '" + principal.getName() + "'");
return (true);
}
And since I've set the principal to something besides null, I had
assumed that the basic authentication would just be skipped. Which is
not the behavior that I'm seeing. Instead, I end up asking the user
to log in twice: once for my custom Valve (which is a web
form/redirect thing), and a second time when they hit a servlet in a
context with basic authentication (which causes the browser to put up
the basic authentication dialog).
So, what am I missing?
Thanks,
Scott
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Tim Funk <fu...@joedog.org>.
How about placing it inside <host> like the SSO valve?
http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/host.html#Single%20Sign%20On
I don't think you'll need to write a Realm. Realms are for mapping roles.
(and authentication)
http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/realm.html
-Tim
Scott Kelley wrote:
> Aha, you're right!
>
> First problem, I didn't have the right logging enabled; I hadn't noticed
> that I didn't see any of the log messages from BasicAuthenticator.java.
>
> Second problem, with logging cranked up appropriately, is that
> BasicAuthenticator gets called before my code.
>
> Which leads to my next question: how can I get called before
> BasicAuthenticator?
>
> I had the Valve installed as the first item in the Engine; when it's
> there it apparently gets called after BasicAuthenticator. I tried moving
> my valve up a level into the Service, but my code didn't seem to get
> called at all when I installed the valve there.
>
> Let me ask a related question: If I have a valve that's setting the
> principal and authType, do I need to set a Realm in server.xml, and if
> so, what should I set it to? Do I need to write a Realm that somehow
> talks to my Valve (since the request info isn't available in Tomcat 4)?
> This is, I think, the piece of the puzzle that I don't completely
> understand.
>
> Scott
>
>
> At 5:03 PM -0400 6/11/03, Tim Funk wrote:
>
>> I took a little longer look. All "looks" ok to me. Turn up debugging.
>> Are you sure that your valve is being executed before the
>> BasicAuthenticator valve?
>>
>> -Tim
>>
>>
>> Scott Kelley wrote:
>>
>>> SingleSignOn has much the same code as BasicAuthenticator:
>>>
>>> in org.apache.catalina.authenticator.SingleSignOn.java:
>>>
>>> // Look up the cached Principal associated with this cookie
>>> value
>>> if (debug >= 1)
>>> log(" Checking for cached principal for " +
>>> cookie.getValue());
>>> SingleSignOnEntry entry = lookup(cookie.getValue());
>>> if (entry != null) {
>>> if (debug >= 1)
>>> log(" Found cached principal '" +
>>> entry.principal.getName() + "' with auth type '" +
>>> entry.authType + "'");
>>> request.setNote(Constants.REQ_SSOID_NOTE,
>>> cookie.getValue());
>>> ((HttpRequest) request).setAuthType(entry.authType);
>>> ((HttpRequest) request).setUserPrincipal(entry.principal);
>>> } else {
>>> if (debug >= 1)
>>> log(" No cached principal found, erasing SSO cookie");
>>> cookie.setMaxAge(0);
>>> hres.addCookie(cookie);
>>> }
>>>
>>> // Invoke the next Valve in our pipeline
>>> context.invokeNext(request, response);
>>>
>>> The only piece of that I'm not doing is the setNote() part; I *think*
>>> that's only used for the form-based login stuff, but I'm not entirely
>>> sure-- that's probably the part of the puzzle I still don't
>>> understand. The basic authenicator doesn't seem to use it.
>>>
>>> Scott
>>>
>>> At 3:10 PM -0400 6/11/03, Tim Funk wrote:
>>>
>>>> I don't have time to see whats wrong, but check the
>>>> SingleSignOnValve as a reference to compare your code.
>>>>
>>>> -Tim
>>>>
>>>> Scott Kelley wrote:
>>>>
>>>>> We've had an Apache/Tomcat configuration deployed for a couple
>>>>> years now. Authentication is handled by a custom Apache plugin
>>>>> written in C. Everything works great and has been quite reliable.
>>>>>
>>>>> Now we would like to move to a standalone Tomcat configuration and
>>>>> have been investigating writing a Valve/Authenticator to replace
>>>>> our existing Apache plugin.
>>>>>
>>>>> I've written a prototype Valve and it does almost everything we
>>>>> need. This gives us the ability to require a server-wide login
>>>>> independent of how the individual servlet contexts are configured.
>>>>> This ends up being Tomcat-specific, but we're ok with that.
>>>>>
>>>>> The only problem with the current prototype is that if a user hits
>>>>> a servlet or JSP in a Context that's configured for basic
>>>>> authentication, they still get the browser-generated basic login
>>>>> dialog, even after being logged in with our Valve.
>>>>>
>>>>> In my code, I check for a particular cookie, and if I find it, I
>>>>> set the user principal in the request to the appropriate user,
>>>>> something like this:
>>>>>
>>>>> // Has connection already been authenticated
>>>>> // (i.e. do we have the login cookie?)
>>>>> Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
>>>>>
>>>>> // If the request has the login cookie, let it pass through
>>>>> if (lcookie!=null) {
>>>>> log("Found login cookie, validating");
>>>>> if (validLoginCookie(lcookie,hreq)) {
>>>>> log("cookie is valid, allowing request");
>>>>> // See AuthenticatorBase.invoke(), which also sets
>>>>> authType and userPrincipal
>>>>> // See SignleSignOn.invoke(), which also set authType
>>>>> and userPrincipal
>>>>> hrequest.getRequest().setUserPrincipal(new
>>>>> TempPrincipal("bob_temp_user"));
>>>>> hrequest.getRequest().setAuthType("BASIC");
>>>>> context.invokeNext(request,response);
>>>>> } else {
>>>>> log("cookie not valid, going to error page");
>>>>> hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
>>>>> }
>>>>> return;
>>>>> }
>>>>>
>>>>> I had thought that this would work, because later in the pipeline
>>>>> the request hits BasicAuthenticator, which does this:
>>>>>
>>>>> public boolean authenticate(HttpRequest request,
>>>>> HttpResponse response,
>>>>> LoginConfig config)
>>>>> throws IOException {
>>>>>
>>>>> // Have we already authenticated someone?
>>>>> Principal principal =
>>>>> ((HttpServletRequest)
>>>>> request.getRequest()).getUserPrincipal();
>>>>> if (principal != null) {
>>>>> if (debug >= 1)
>>>>> log("Already authenticated '" + principal.getName()
>>>>> + "'");
>>>>> return (true);
>>>>> }
>>>>>
>>>>>
>>>>> And since I've set the principal to something besides null, I had
>>>>> assumed that the basic authentication would just be skipped. Which
>>>>> is not the behavior that I'm seeing. Instead, I end up asking the
>>>>> user to log in twice: once for my custom Valve (which is a web
>>>>> form/redirect thing), and a second time when they hit a servlet in
>>>>> a context with basic authentication (which causes the browser to
>>>>> put up the basic authentication dialog).
>>>>>
>>>>> So, what am I missing?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Scott
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Tim Funk <fu...@joedog.org>.
Sweet! (Says the guy who has to write a CustomValve for work in the near future)
-Tim
Bill Barker wrote:
> BasicAutheniticator is a Context-level Valve, so it can't possibly get
> invoked before an Engine-level Valve. You've got something really strange
> in your setup.
>
> The other thing to point out is that if you configure your Valve at the
> Context-level, and implement org.apache.catalina.Authenticator, then
> BasicAuthenticator won't even be installed. Tomcat will trust that you know
> what you are doing, and leave all authentication to your Valve.
>
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Bill Barker <wb...@wilshire.com>.
BasicAutheniticator is a Context-level Valve, so it can't possibly get
invoked before an Engine-level Valve. You've got something really strange
in your setup.
The other thing to point out is that if you configure your Valve at the
Context-level, and implement org.apache.catalina.Authenticator, then
BasicAuthenticator won't even be installed. Tomcat will trust that you know
what you are doing, and leave all authentication to your Valve.
"Scott Kelley" <sk...@biomail.ucsd.edu> wrote in message
news:p0521060ebb0d77c31bb0@[132.239.58.113]...
> Aha, you're right!
>
> First problem, I didn't have the right logging enabled; I hadn't
> noticed that I didn't see any of the log messages from
> BasicAuthenticator.java.
>
> Second problem, with logging cranked up appropriately, is that
> BasicAuthenticator gets called before my code.
>
> Which leads to my next question: how can I get called before
> BasicAuthenticator?
>
> I had the Valve installed as the first item in the Engine; when it's
> there it apparently gets called after BasicAuthenticator. I tried
> moving my valve up a level into the Service, but my code didn't seem
> to get called at all when I installed the valve there.
>
> Let me ask a related question: If I have a valve that's setting the
> principal and authType, do I need to set a Realm in server.xml, and
> if so, what should I set it to? Do I need to write a Realm that
> somehow talks to my Valve (since the request info isn't available in
> Tomcat 4)? This is, I think, the piece of the puzzle that I don't
> completely understand.
>
> Scott
>
>
> At 5:03 PM -0400 6/11/03, Tim Funk wrote:
> >I took a little longer look. All "looks" ok to me. Turn up
> >debugging. Are you sure that your valve is being executed before the
> >BasicAuthenticator valve?
> >
> >-Tim
> >
> >
> >Scott Kelley wrote:
> >>SingleSignOn has much the same code as BasicAuthenticator:
> >>
> >>in org.apache.catalina.authenticator.SingleSignOn.java:
> >>
> >> // Look up the cached Principal associated with this cookie
value
> >> if (debug >= 1)
> >> log(" Checking for cached principal for " +
cookie.getValue());
> >> SingleSignOnEntry entry = lookup(cookie.getValue());
> >> if (entry != null) {
> >> if (debug >= 1)
> >> log(" Found cached principal '" +
> >> entry.principal.getName() + "' with auth type '" +
> >> entry.authType + "'");
> >> request.setNote(Constants.REQ_SSOID_NOTE,
cookie.getValue());
> >> ((HttpRequest) request).setAuthType(entry.authType);
> >> ((HttpRequest) request).setUserPrincipal(entry.principal);
> >> } else {
> >> if (debug >= 1)
> >> log(" No cached principal found, erasing SSO cookie");
> >> cookie.setMaxAge(0);
> >> hres.addCookie(cookie);
> >> }
> >>
> >> // Invoke the next Valve in our pipeline
> >> context.invokeNext(request, response);
> >>
> >>The only piece of that I'm not doing is the setNote() part; I
> >>*think* that's only used for the form-based login stuff, but I'm
> >>not entirely sure-- that's probably the part of the puzzle I still
> >>don't understand. The basic authenicator doesn't seem to use it.
> >>
> >>Scott
> >>
> >>At 3:10 PM -0400 6/11/03, Tim Funk wrote:
> >>
> >>>I don't have time to see whats wrong, but check the
> >>>SingleSignOnValve as a reference to compare your code.
> >>>
> >>>-Tim
> >>>
> >>>Scott Kelley wrote:
> >>>
> >>>>We've had an Apache/Tomcat configuration deployed for a couple
> >>>>years now. Authentication is handled by a custom Apache plugin
> >>>>written in C. Everything works great and has been quite reliable.
> >>>>
> >>>>Now we would like to move to a standalone Tomcat configuration
> >>>>and have been investigating writing a Valve/Authenticator to
> >>>>replace our existing Apache plugin.
> >>>>
> >>>>I've written a prototype Valve and it does almost everything we
> >>>>need. This gives us the ability to require a server-wide login
> >>>>independent of how the individual servlet contexts are
> >>>>configured. This ends up being Tomcat-specific, but we're ok with
> >>>>that.
> >>>>
> >>>>The only problem with the current prototype is that if a user
> >>>>hits a servlet or JSP in a Context that's configured for basic
> >>>>authentication, they still get the browser-generated basic login
> >>>>dialog, even after being logged in with our Valve.
> >>>>
> >>>>In my code, I check for a particular cookie, and if I find it, I
> >>>>set the user principal in the request to the appropriate user,
> >>>>something like this:
> >>>>
> >>>> // Has connection already been authenticated
> >>>> // (i.e. do we have the login cookie?)
> >>>> Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
> >>>>
> >>>> // If the request has the login cookie, let it pass through
> >>>> if (lcookie!=null) {
> >>>> log("Found login cookie, validating");
> >>>> if (validLoginCookie(lcookie,hreq)) {
> >>>> log("cookie is valid, allowing request");
> >>>> // See AuthenticatorBase.invoke(), which also sets
> >>>>authType and userPrincipal
> >>>> // See SignleSignOn.invoke(), which also set authType
> >>>>and userPrincipal
> >>>> hrequest.getRequest().setUserPrincipal(new
> >>>>TempPrincipal("bob_temp_user"));
> >>>> hrequest.getRequest().setAuthType("BASIC");
> >>>> context.invokeNext(request,response);
> >>>> } else {
> >>>> log("cookie not valid, going to error page");
> >>>>
hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
> >>>> }
> >>>> return;
> >>>> }
> >>>>
> >>>>I had thought that this would work, because later in the pipeline
> >>>>the request hits BasicAuthenticator, which does this:
> >>>>
> >>>> public boolean authenticate(HttpRequest request,
> >>>> HttpResponse response,
> >>>> LoginConfig config)
> >>>> throws IOException {
> >>>>
> >>>> // Have we already authenticated someone?
> >>>> Principal principal =
> >>>> ((HttpServletRequest)
request.getRequest()).getUserPrincipal();
> >>>> if (principal != null) {
> >>>> if (debug >= 1)
> >>>> log("Already authenticated '" + principal.getName() +
"'");
> >>>> return (true);
> >>>> }
> >>>>
> >>>>
> >>>>And since I've set the principal to something besides null, I had
> >>>>assumed that the basic authentication would just be skipped.
> >>>>Which is not the behavior that I'm seeing. Instead, I end up
> >>>>asking the user to log in twice: once for my custom Valve (which
> >>>>is a web form/redirect thing), and a second time when they hit a
> >>>>servlet in a context with basic authentication (which causes the
> >>>>browser to put up the basic authentication dialog).
> >>>>
> >>>>So, what am I missing?
> >>>>
> >>>>Thanks,
> >>>>
> >>>>Scott
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Scott Kelley <sk...@biomail.ucsd.edu>.
Aha, you're right!
First problem, I didn't have the right logging enabled; I hadn't
noticed that I didn't see any of the log messages from
BasicAuthenticator.java.
Second problem, with logging cranked up appropriately, is that
BasicAuthenticator gets called before my code.
Which leads to my next question: how can I get called before
BasicAuthenticator?
I had the Valve installed as the first item in the Engine; when it's
there it apparently gets called after BasicAuthenticator. I tried
moving my valve up a level into the Service, but my code didn't seem
to get called at all when I installed the valve there.
Let me ask a related question: If I have a valve that's setting the
principal and authType, do I need to set a Realm in server.xml, and
if so, what should I set it to? Do I need to write a Realm that
somehow talks to my Valve (since the request info isn't available in
Tomcat 4)? This is, I think, the piece of the puzzle that I don't
completely understand.
Scott
At 5:03 PM -0400 6/11/03, Tim Funk wrote:
>I took a little longer look. All "looks" ok to me. Turn up
>debugging. Are you sure that your valve is being executed before the
>BasicAuthenticator valve?
>
>-Tim
>
>
>Scott Kelley wrote:
>>SingleSignOn has much the same code as BasicAuthenticator:
>>
>>in org.apache.catalina.authenticator.SingleSignOn.java:
>>
>> // Look up the cached Principal associated with this cookie value
>> if (debug >= 1)
>> log(" Checking for cached principal for " + cookie.getValue());
>> SingleSignOnEntry entry = lookup(cookie.getValue());
>> if (entry != null) {
>> if (debug >= 1)
>> log(" Found cached principal '" +
>> entry.principal.getName() + "' with auth type '" +
>> entry.authType + "'");
>> request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
>> ((HttpRequest) request).setAuthType(entry.authType);
>> ((HttpRequest) request).setUserPrincipal(entry.principal);
>> } else {
>> if (debug >= 1)
>> log(" No cached principal found, erasing SSO cookie");
>> cookie.setMaxAge(0);
>> hres.addCookie(cookie);
>> }
>>
>> // Invoke the next Valve in our pipeline
>> context.invokeNext(request, response);
>>
>>The only piece of that I'm not doing is the setNote() part; I
>>*think* that's only used for the form-based login stuff, but I'm
>>not entirely sure-- that's probably the part of the puzzle I still
>>don't understand. The basic authenicator doesn't seem to use it.
>>
>>Scott
>>
>>At 3:10 PM -0400 6/11/03, Tim Funk wrote:
>>
>>>I don't have time to see whats wrong, but check the
>>>SingleSignOnValve as a reference to compare your code.
>>>
>>>-Tim
>>>
>>>Scott Kelley wrote:
>>>
>>>>We've had an Apache/Tomcat configuration deployed for a couple
>>>>years now. Authentication is handled by a custom Apache plugin
>>>>written in C. Everything works great and has been quite reliable.
>>>>
>>>>Now we would like to move to a standalone Tomcat configuration
>>>>and have been investigating writing a Valve/Authenticator to
>>>>replace our existing Apache plugin.
>>>>
>>>>I've written a prototype Valve and it does almost everything we
>>>>need. This gives us the ability to require a server-wide login
>>>>independent of how the individual servlet contexts are
>>>>configured. This ends up being Tomcat-specific, but we're ok with
>>>>that.
>>>>
>>>>The only problem with the current prototype is that if a user
>>>>hits a servlet or JSP in a Context that's configured for basic
>>>>authentication, they still get the browser-generated basic login
>>>>dialog, even after being logged in with our Valve.
>>>>
>>>>In my code, I check for a particular cookie, and if I find it, I
>>>>set the user principal in the request to the appropriate user,
>>>>something like this:
>>>>
>>>> // Has connection already been authenticated
>>>> // (i.e. do we have the login cookie?)
>>>> Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
>>>>
>>>> // If the request has the login cookie, let it pass through
>>>> if (lcookie!=null) {
>>>> log("Found login cookie, validating");
>>>> if (validLoginCookie(lcookie,hreq)) {
>>>> log("cookie is valid, allowing request");
>>>> // See AuthenticatorBase.invoke(), which also sets
>>>>authType and userPrincipal
>>>> // See SignleSignOn.invoke(), which also set authType
>>>>and userPrincipal
>>>> hrequest.getRequest().setUserPrincipal(new
>>>>TempPrincipal("bob_temp_user"));
>>>> hrequest.getRequest().setAuthType("BASIC");
>>>> context.invokeNext(request,response);
>>>> } else {
>>>> log("cookie not valid, going to error page");
>>>> hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
>>>> }
>>>> return;
>>>> }
>>>>
>>>>I had thought that this would work, because later in the pipeline
>>>>the request hits BasicAuthenticator, which does this:
>>>>
>>>> public boolean authenticate(HttpRequest request,
>>>> HttpResponse response,
>>>> LoginConfig config)
>>>> throws IOException {
>>>>
>>>> // Have we already authenticated someone?
>>>> Principal principal =
>>>> ((HttpServletRequest) request.getRequest()).getUserPrincipal();
>>>> if (principal != null) {
>>>> if (debug >= 1)
>>>> log("Already authenticated '" + principal.getName() + "'");
>>>> return (true);
>>>> }
>>>>
>>>>
>>>>And since I've set the principal to something besides null, I had
>>>>assumed that the basic authentication would just be skipped.
>>>>Which is not the behavior that I'm seeing. Instead, I end up
>>>>asking the user to log in twice: once for my custom Valve (which
>>>>is a web form/redirect thing), and a second time when they hit a
>>>>servlet in a context with basic authentication (which causes the
>>>>browser to put up the basic authentication dialog).
>>>>
>>>>So, what am I missing?
>>>>
>>>>Thanks,
>>>>
>>>>Scott
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Tim Funk <fu...@joedog.org>.
I took a little longer look. All "looks" ok to me. Turn up debugging. Are you
sure that your valve is being executed before the BasicAuthenticator valve?
-Tim
Scott Kelley wrote:
> SingleSignOn has much the same code as BasicAuthenticator:
>
> in org.apache.catalina.authenticator.SingleSignOn.java:
>
> // Look up the cached Principal associated with this cookie value
> if (debug >= 1)
> log(" Checking for cached principal for " + cookie.getValue());
> SingleSignOnEntry entry = lookup(cookie.getValue());
> if (entry != null) {
> if (debug >= 1)
> log(" Found cached principal '" +
> entry.principal.getName() + "' with auth type '" +
> entry.authType + "'");
> request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
> ((HttpRequest) request).setAuthType(entry.authType);
> ((HttpRequest) request).setUserPrincipal(entry.principal);
> } else {
> if (debug >= 1)
> log(" No cached principal found, erasing SSO cookie");
> cookie.setMaxAge(0);
> hres.addCookie(cookie);
> }
>
> // Invoke the next Valve in our pipeline
> context.invokeNext(request, response);
>
> The only piece of that I'm not doing is the setNote() part; I *think*
> that's only used for the form-based login stuff, but I'm not entirely
> sure-- that's probably the part of the puzzle I still don't understand.
> The basic authenicator doesn't seem to use it.
>
> Scott
>
> At 3:10 PM -0400 6/11/03, Tim Funk wrote:
>
>> I don't have time to see whats wrong, but check the SingleSignOnValve
>> as a reference to compare your code.
>>
>> -Tim
>>
>> Scott Kelley wrote:
>>
>>> We've had an Apache/Tomcat configuration deployed for a couple years
>>> now. Authentication is handled by a custom Apache plugin written in
>>> C. Everything works great and has been quite reliable.
>>>
>>> Now we would like to move to a standalone Tomcat configuration and
>>> have been investigating writing a Valve/Authenticator to replace our
>>> existing Apache plugin.
>>>
>>> I've written a prototype Valve and it does almost everything we need.
>>> This gives us the ability to require a server-wide login independent
>>> of how the individual servlet contexts are configured. This ends up
>>> being Tomcat-specific, but we're ok with that.
>>>
>>> The only problem with the current prototype is that if a user hits a
>>> servlet or JSP in a Context that's configured for basic
>>> authentication, they still get the browser-generated basic login
>>> dialog, even after being logged in with our Valve.
>>>
>>> In my code, I check for a particular cookie, and if I find it, I set
>>> the user principal in the request to the appropriate user, something
>>> like this:
>>>
>>> // Has connection already been authenticated
>>> // (i.e. do we have the login cookie?)
>>> Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
>>>
>>> // If the request has the login cookie, let it pass through
>>> if (lcookie!=null) {
>>> log("Found login cookie, validating");
>>> if (validLoginCookie(lcookie,hreq)) {
>>> log("cookie is valid, allowing request");
>>> // See AuthenticatorBase.invoke(), which also sets
>>> authType and userPrincipal
>>> // See SignleSignOn.invoke(), which also set authType and
>>> userPrincipal
>>> hrequest.getRequest().setUserPrincipal(new
>>> TempPrincipal("bob_temp_user"));
>>> hrequest.getRequest().setAuthType("BASIC");
>>> context.invokeNext(request,response);
>>> } else {
>>> log("cookie not valid, going to error page");
>>> hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
>>> }
>>> return;
>>> }
>>>
>>> I had thought that this would work, because later in the pipeline the
>>> request hits BasicAuthenticator, which does this:
>>>
>>> public boolean authenticate(HttpRequest request,
>>> HttpResponse response,
>>> LoginConfig config)
>>> throws IOException {
>>>
>>> // Have we already authenticated someone?
>>> Principal principal =
>>> ((HttpServletRequest)
>>> request.getRequest()).getUserPrincipal();
>>> if (principal != null) {
>>> if (debug >= 1)
>>> log("Already authenticated '" + principal.getName() +
>>> "'");
>>> return (true);
>>> }
>>>
>>>
>>> And since I've set the principal to something besides null, I had
>>> assumed that the basic authentication would just be skipped. Which is
>>> not the behavior that I'm seeing. Instead, I end up asking the user
>>> to log in twice: once for my custom Valve (which is a web
>>> form/redirect thing), and a second time when they hit a servlet in a
>>> context with basic authentication (which causes the browser to put up
>>> the basic authentication dialog).
>>>
>>> So, what am I missing?
>>>
>>> Thanks,
>>>
>>> Scott
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Scott Kelley <sk...@biomail.ucsd.edu>.
SingleSignOn has much the same code as BasicAuthenticator:
in org.apache.catalina.authenticator.SingleSignOn.java:
// Look up the cached Principal associated with this cookie value
if (debug >= 1)
log(" Checking for cached principal for " + cookie.getValue());
SingleSignOnEntry entry = lookup(cookie.getValue());
if (entry != null) {
if (debug >= 1)
log(" Found cached principal '" +
entry.principal.getName() + "' with auth type '" +
entry.authType + "'");
request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
((HttpRequest) request).setAuthType(entry.authType);
((HttpRequest) request).setUserPrincipal(entry.principal);
} else {
if (debug >= 1)
log(" No cached principal found, erasing SSO cookie");
cookie.setMaxAge(0);
hres.addCookie(cookie);
}
// Invoke the next Valve in our pipeline
context.invokeNext(request, response);
The only piece of that I'm not doing is the setNote() part; I *think*
that's only used for the form-based login stuff, but I'm not entirely
sure-- that's probably the part of the puzzle I still don't
understand. The basic authenicator doesn't seem to use it.
Scott
At 3:10 PM -0400 6/11/03, Tim Funk wrote:
>I don't have time to see whats wrong, but check the
>SingleSignOnValve as a reference to compare your code.
>
>-Tim
>
>Scott Kelley wrote:
>>We've had an Apache/Tomcat configuration deployed for a couple
>>years now. Authentication is handled by a custom Apache plugin
>>written in C. Everything works great and has been quite reliable.
>>
>>Now we would like to move to a standalone Tomcat configuration and
>>have been investigating writing a Valve/Authenticator to replace
>>our existing Apache plugin.
>>
>>I've written a prototype Valve and it does almost everything we
>>need. This gives us the ability to require a server-wide login
>>independent of how the individual servlet contexts are configured.
>>This ends up being Tomcat-specific, but we're ok with that.
>>
>>The only problem with the current prototype is that if a user hits
>>a servlet or JSP in a Context that's configured for basic
>>authentication, they still get the browser-generated basic login
>>dialog, even after being logged in with our Valve.
>>
>>In my code, I check for a particular cookie, and if I find it, I
>>set the user principal in the request to the appropriate user,
>>something like this:
>>
>> // Has connection already been authenticated
>> // (i.e. do we have the login cookie?)
>> Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
>>
>> // If the request has the login cookie, let it pass through
>> if (lcookie!=null) {
>> log("Found login cookie, validating");
>> if (validLoginCookie(lcookie,hreq)) {
>> log("cookie is valid, allowing request");
>> // See AuthenticatorBase.invoke(), which also sets
>>authType and userPrincipal
>> // See SignleSignOn.invoke(), which also set authType
>>and userPrincipal
>> hrequest.getRequest().setUserPrincipal(new
>>TempPrincipal("bob_temp_user"));
>> hrequest.getRequest().setAuthType("BASIC");
>> context.invokeNext(request,response);
>> } else {
>> log("cookie not valid, going to error page");
>> hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
>> }
>> return;
>> }
>>
>>I had thought that this would work, because later in the pipeline
>>the request hits BasicAuthenticator, which does this:
>>
>> public boolean authenticate(HttpRequest request,
>> HttpResponse response,
>> LoginConfig config)
>> throws IOException {
>>
>> // Have we already authenticated someone?
>> Principal principal =
>> ((HttpServletRequest) request.getRequest()).getUserPrincipal();
>> if (principal != null) {
>> if (debug >= 1)
>> log("Already authenticated '" + principal.getName() + "'");
>> return (true);
>> }
>>
>>
>>And since I've set the principal to something besides null, I had
>>assumed that the basic authentication would just be skipped. Which
>>is not the behavior that I'm seeing. Instead, I end up asking the
>>user to log in twice: once for my custom Valve (which is a web
>>form/redirect thing), and a second time when they hit a servlet in
>>a context with basic authentication (which causes the browser to
>>put up the basic authentication dialog).
>>
>>So, what am I missing?
>>
>>Thanks,
>>
>>Scott
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
Re: Valve as Custom Authenticator
Posted by Tim Funk <fu...@joedog.org>.
I don't have time to see whats wrong, but check the SingleSignOnValve as a
reference to compare your code.
-Tim
Scott Kelley wrote:
> We've had an Apache/Tomcat configuration deployed for a couple years
> now. Authentication is handled by a custom Apache plugin written in C.
> Everything works great and has been quite reliable.
>
> Now we would like to move to a standalone Tomcat configuration and have
> been investigating writing a Valve/Authenticator to replace our existing
> Apache plugin.
>
> I've written a prototype Valve and it does almost everything we need.
> This gives us the ability to require a server-wide login independent of
> how the individual servlet contexts are configured. This ends up being
> Tomcat-specific, but we're ok with that.
>
> The only problem with the current prototype is that if a user hits a
> servlet or JSP in a Context that's configured for basic authentication,
> they still get the browser-generated basic login dialog, even after
> being logged in with our Valve.
>
> In my code, I check for a particular cookie, and if I find it, I set the
> user principal in the request to the appropriate user, something like this:
>
> // Has connection already been authenticated
> // (i.e. do we have the login cookie?)
> Cookie lcookie=ValveUtils.findCookie(hreq,LOGIN_COOKIE_NAME);
>
> // If the request has the login cookie, let it pass through
> if (lcookie!=null) {
> log("Found login cookie, validating");
> if (validLoginCookie(lcookie,hreq)) {
> log("cookie is valid, allowing request");
> // See AuthenticatorBase.invoke(), which also sets authType
> and userPrincipal
> // See SignleSignOn.invoke(), which also set authType and
> userPrincipal
> hrequest.getRequest().setUserPrincipal(new
> TempPrincipal("bob_temp_user"));
> hrequest.getRequest().setAuthType("BASIC");
> context.invokeNext(request,response);
> } else {
> log("cookie not valid, going to error page");
> hres.sendRedirect(hres.encodeRedirectURL(ERROR_PAGE_URI));
> }
> return;
> }
>
> I had thought that this would work, because later in the pipeline the
> request hits BasicAuthenticator, which does this:
>
> public boolean authenticate(HttpRequest request,
> HttpResponse response,
> LoginConfig config)
> throws IOException {
>
> // Have we already authenticated someone?
> Principal principal =
> ((HttpServletRequest) request.getRequest()).getUserPrincipal();
> if (principal != null) {
> if (debug >= 1)
> log("Already authenticated '" + principal.getName() + "'");
> return (true);
> }
>
>
> And since I've set the principal to something besides null, I had
> assumed that the basic authentication would just be skipped. Which is
> not the behavior that I'm seeing. Instead, I end up asking the user to
> log in twice: once for my custom Valve (which is a web form/redirect
> thing), and a second time when they hit a servlet in a context with
> basic authentication (which causes the browser to put up the basic
> authentication dialog).
>
> So, what am I missing?
>
> Thanks,
>
> Scott
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org