Bug 22617 - BASIC authentication fails if Realm supports default user
Summary: BASIC authentication fails if Realm supports default user
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 4
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 4.1.24
Hardware: All All
: P3 major with 1 vote (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-08-21 08:11 UTC by Michael Lipp
Modified: 2005-04-28 13:00 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Lipp 2003-08-21 08:11:11 UTC
If I use BASIC authentication, tomcat obviously tries to authenticate an initial
request against the security provider although the request does not include the
"Authorization: ..." header yet! I have not tracked what credentials are used
but the assumption in the tomcat implementation seems to be that trying
authorization with the used "default credentials" should fail anyway, causing
tomcat to then send the 401 reply and the browser to display the login dialog.

Although I have to admit that I could not find something specific in the
specifications, I think this behaviour is a bug. Tomcat should query the
security provider only if it has received the "Authorization: ..." header as
part of the request. Any request of a resource secured with BASIC authentication
that lacks this header should result in an immediate 401 response, i.e. without
consulting the security provider.

Why is this important? Well, especially in a J2EE environment a security realm
may support something like an "unauthenticated identity" used for anonymous
access of certain resources (but not the servlet in question). The current
behaviour of tomcat has the effect that there is an authorization request
without credentials and the user is (without ever being prompted by the browser)
identified as the anonymous user. As tomcat thinks identification has been
successfully performed, it does not repond with a 401 but rather continues
processing with the unauthenticated identity. This identity may (usually does)
lack a lot of the rights that an authenticated user has and thus the user
receives a 403.
Comment 1 Mark Thomas 2005-04-14 22:53:24 UTC
The closest thing I could find in the spec to what you describe is in J2EE.3.4.3
Unauthenticated Users.

This makes clear that the anonymous user is unathenticated and that the
container is responsible for providing a suitable principal for unauthenitcated
users to the EJB container.

Authentication is only required for protected resources and Tomcat will only
prompt for authentication when accessing a protected resource.

Tomcat is consistent with the required behaviour.
Comment 2 Michael Lipp 2005-04-15 09:19:01 UTC
> Authentication is only required for protected resources and Tomcat will only
> prompt for authentication when accessing a protected resource.

This is wrong. The whole point is that Tomcat DOES NOT PROMPT when basic
authentication is used. If the security module allows an unauthenticated user,
you never get the opportunity to authenticate as someone different, because
Tomcat never sends 401 to the browser.

Tomcat finds that the resource I'm trying to access is protected. This is OK.
But instead of sending a 401 and give me the opportunity to provide credentials,
it obviously immediately tries to "authenticate as unauthenticated user". If
this is successful, it simply continues with this identity and I never get a prompt.

Acing like this, Tomcat is not consistent in its behaviour. Try form based
authentication instead. If you use form based authentication, Tomcat ALWAYS
shows the login form first, even if the security realm supports an
unauthenticated identity. If form based authentication had been implemented just
as basic authentication, Tomcat would find that the resource is protected, try
to authenticate, find that the "unautheticated identity" works and continue with
this identity, never showing the login form. But it does!

The point is that basic authentication and form based authentication behave
differently when the security realm supports an unauthenticated identity. Using
form based authentication, you are prompted for credentials; using basic
authentication, you are not prompted. You cannot derive from the specs which
behaviour is correct, I agree with this. However, Tomcat should consistently
stick to one of those possibilities and should not act differently depending on
the authentication method chosen.
Comment 3 Mark Thomas 2005-04-27 23:59:45 UTC
I have done some testing with the latest code from CVS but the behaviour should
be the same with 4.1.24

The key is how your realm authenticates when username=null and when username=""

username=null when there are no authentication headers
username=""   when there are headers but the user just hit enter on the BASIC
auth dialog

I have tested this with the memory realm with entries in tomcat-users.xml of the
form:
<user username="" password="" roles="bug22617"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>

and web.xml entries that look like:
  <security-constraint>
    <display-name>Bug 22617</display-name>
    <web-resource-collection>
      <web-resource-name>Bug 22617</web-resource-name>
      <url-pattern>/bug22617/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>bug22617</role-name>
      <role-name>tomcat</role-name>
    </auth-constraint>
  </security-constraint>

  <login-config>
    <auth-method>BASIC</auth-method>
  </login-config>

With this configuration I always get prompted for a user name and password and
just pressing enter or using tomcat/tomact allows me to see the page.

Based on this, I am pretty sure you need to change your Realm implementation so
that username=null always fails authentication. Given that Realm is an internal
Tomcat interface, I don't see this as being an unreasonable requirement to be
placed on custom Realm implementations.

I agree that the behaviour is inconsistent if the Realm treats username=null and
username="" as equivalent. However, I believe such behaviour in a realm is not
correct.

I'll leave this open for now until you respond, but I am minded to close this as
invalid.
Comment 4 Michael Lipp 2005-04-28 11:15:16 UTC
I think you are bluring the distinction between a user not being identified
(yet) and thus being "null" and the user with name "". I admit that the latter
is a very short username, but -- as you state -- this is what the browser-user
has entered by simply hitting enter.

In my opinion, user "" is no longer anonymous, it is simply a user with a very
short name. Of course, a Realm implementation may take this as a shortcut for
"anonymous" or "nobody", and assign the "unauthenticated identity", but it may
as well require a password for this username. 

I still consider it an error that Tomcat calls the Realm implementation at all
if authentication is BASIC and it has not received any authentication headers
yet. It should simply have the browser prompt the user for credentials, just
like form based authentication ALWAYS displays the form (and does not call the
Realm implementation first with username being "null").

Of course, the Realm interface is an internal interface. But the point is that
Tomcat invokes this interface differently depending on the authentication method
used!

The practical problem is that I actually do not supply the realm implementation,
JBoss does. I simply supply a JAAS login module. And in a J2EE/JBoss context, I
have to accept a user being "null" as the anonymous user, because this is what
my J2EE clients use as credentials when trying to access anonymously (if I was
to follow your line, a client that wanted to act with the unauthenticated
identity would have to include the necesary code to set the username to "" -- I
don't think this is reasonable). Now don't say "well this is a JBoss problem"; I
strongly doubt that e.g. Geronimo uses username "" instead of user being "null"
to represent an anonymous client.

I still think a fix would be quite simple: if ((authentication == BASIC) AND (no
authentication headers)) { "send 401 to browser" }. This would make the
behaviour consistent with form based login (and Jetty and WebLogicServer, btw.
-- not being able to derive the correct behaviour from the specifications, this
may be a point). As a user, I can still hit the return key and if the Realm
implementation allows anonymous access, it can assign the "unauthenticated
identity" if username is "" and password is "" (as you have proposed the Realm
implementation should).
Comment 5 Mark Thomas 2005-04-28 21:00:21 UTC
Got it. As soon as I read your last post it all made sense.

Your are right, this is a bug and the fix is simple.

I have commited a fix for this to TC4.1.x and TC5.5.x