Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP Authentication and Authorization Failure always sending 401 Challenge #638

Open
pedroneil opened this issue Jul 5, 2018 · 6 comments

Comments

@pedroneil
Copy link
Contributor

pedroneil commented Jul 5, 2018

HTTP Authentication Failures are always always returning a challenge.

The Challenge and Response RFC does not require that a Server sends a Challenge for Failed Authentication but if it does require that when a server sends a 401 then it must send 1 or more WWW-Authenticate headers with a comma separated list of parameters describing the Authentication Scheme.

I need thee the following from NegotiateSecurityFilter abilities

  1. to not challenge on Failed Authentication; especially Basic
  2. hide resources when there is not Authorization Header
  3. hide resources when there is an Authentication failure
  4. specify the order of NTLM and Negotiate for WWW-Authenticate challenges, e.g. Workgroups, Domains and no local credential manager
    1. these are the following orders that required for various deployments,
    2. Basic,, NTLM, Negotiate
    3. NTLM, Negotiate, Basic
    4. Basic, Negotiate, NTLM
    5. Negotiate, NTLM, Basic

See this MDN article for HTTP Basic Authentication Challenge and Basic Authentication Failure

RFC7617 obsoletes RFC2617 which is the current implementation of BasicSecurityFilterProvider

IE and Chrome preemptive Authorization Headers Domain / Enterprise Deployments of Negotiate Security Filter

Withe reference RFC7235#section-3.1 and RFC7231#section-6.5.3 a server is not required to return a challenge and the server can choose to hide the existence of a resource by sending a 404 instead of a 403, (IIS and .NET supports this configuration option) and considering that AD configuration for IE and Chrome for Business provide the ability to use Negotiate or NTLM preemptive means that NegotiateSecurityFilter could be configured to hide the existence of a resource.


extract from RFC7617
Upon receipt of a request for a URI within the protection space that
lacks credentials, the server can reply with a challenge using the
401 (Unauthorized) status code ([RFC7235], Section 3.1) and the
WWW-Authenticate header field ([RFC7235], Section 4.1).

   For instance:

      HTTP/1.1 401 Unauthorized
      Date: Mon, 04 Feb 2014 16:50:53 GMT
      WWW-Authenticate: Basic realm="WallyWorld"

I would like to modify NegotiateSecurityFilter or create a new Filter that Extends NegotiateSecurityFilter to Implement the following

  1. new init parameter permissiveAuthorization
    1. true which will be the default leaving NegotiateSecurityFilter to continue to work as is current and will set WWW-Authenticate for requests with Authorization Header
    2. false no Challenges are sent to Requests with no Authorization Header
  2. new init parameter hideResources - mutually exclusive of permissiveAuthorization - for failed authentication if hideResources = true, return 404 else return 403
  3. new init parameter challengeFailedAuthentication

Notes on permissiveAuthorization and hideResources:

during Initialization of NegotiateSecurityFilter if permissiveAuthorization is false and hideResources = fase = throw ConflictingParameterRuntimeException message = 404 response will be returned for Forbidden access because permissiveAuthorization has been disabled permissiveAuthorization = false

Notes on behaviour of NegotiateSecurityFilter with the new parameters and only a BasicSecurityFilterProvider configured

no Authorization header and permissiveAuthorization = false then return 404
no Authorization header and permissiveAuthorization = true then return 403
no Authorization header and permissiveAuthorization = true and hideResources = true then return 403

no Authorization header and permissiveAuthorization = false and hideResources = false then return 404

Notes about allowGuestLogon false hideResources and successful authentication

  1. a successful password authentication where allowGuestLogin is false, if hideResources then return a 404 otherwise return 403

https://tools.ietf.org/html/rfc7231#section-6.5.3

A server that receives valid credentials that are not adequate to
gain access ought to respond with the 403 (Forbidden) status code
(Section 6.5.3 of [RFC7231]).

The Client MAY submit credentials when receiving a WWW-Authenticate and the Client MAY
preemptivley submit an Authorization on first request to a resource
If failed Authentication then return with 403 or 404 [RFC7231 7231#section-6.5.3)(https://tools.ietf.org/html/rfc7231#section-6.5.3)

6.5.3. 403 Forbidden

   The 403 (Forbidden) status code indicates that the server understood
   the request but refuses to authorize it.  A server that wishes to
   make public why the request has been forbidden can describe that
   reason in the response payload (if any).

   If authentication credentials were provided in the request, the
   server considers them insufficient to grant access.  The client
   SHOULD NOT automatically repeat the request with the same
   credentials.  The client MAY repeat the request with new or different
   credentials.  However, a request might be forbidden for reasons
   unrelated to the credentials.

   An origin server that wishes to "hide" the current existence of a
   forbidden target resource MAY instead respond with a status code of
   404 (Not Found).
@pedroneil pedroneil changed the title Chrome pops up login box if I type my password twice Chrome pops up login box if I type my password wrong Jul 5, 2018
@dblock
Copy link
Collaborator

dblock commented Jul 6, 2018

I think it's the same debate as disableSSO in #636. Personally I am not opposed to an enabled flag in every filter that avoids having to comment the filter out.

Naming wise, I would change disableSSO to enabled and default that to true and implement the same in this filter (and every other) in some base class that prevents calling doFilter altogether.

@pedroneil
Copy link
Contributor Author

pedroneil commented Jul 6, 2018

@dblock thank you very much for the feedback.

I require the basic security filter provider to be enabled and handle a request.

I only don't want the challenge if authorization fails.

This first request to my servlet includes an Authorization: Basic bae64creds and if this fails i dont want the challenge sent because the browser because chrome handles the challenge which causes the pop up box. the speech says.

I'll update my working example, thats in test, to send the challenge if there was no authorization header.

I change my current deployment in Test to use sendChallengeOnFailedAuthorization this will have a default of true and leave the basic security filter provider sending the challenge if there is not Authorization header.

The spec says that the vendor MAY send a challenge if authorization fails, the parameter is to make sure that current deployments work as expected.

That the first request can include the authorization header and the vendor's implementation.

Another approach to address my issue of the browser pop might be to have a Custom Authorzation Scheme and a new Provider waffle.servlet.spi.BasicSecurityFilterProvider/protocols, but adding the parameter and conditionally sending the challenge doesn't go off spec.
NTLM
Negotiate
Basic
xhrBasic

@dblock
Copy link
Collaborator

dblock commented Jul 6, 2018

For enabled I opened #639 so we don't lose it. Maybe someone wants to contribute!

@pedroneil
Copy link
Contributor Author

pedroneil commented Jul 7, 2018

I send the Authorization Header; I do not want to disable any filters

Please see this diagram RFC7617 at MDN where rfc7617 obsoletes 2617 which is the current implementation of BasicSecurityFilterProvider

  1. 401 is a Challenge that the server can reply with a challenge if the resource is protected
  2. In the diagram the Authentication failure is returned a 403 - Forbidden
  3. The Client MAY submit credentials when receiving a WWW-Authenticate

extract from RFC7617

Upon receipt of a request for a URI within the protection space that
lacks credentials, the server can reply with a challenge using the
401 (Unauthorized) status code ([RFC7235], Section 3.1) and the
WWW-Authenticate header field ([RFC7235], Section 4.1).

For instance:

  HTTP/1.1 401 Unauthorized
  Date: Mon, 04 Feb 2014 16:50:53 GMT
  WWW-Authenticate: Basic realm="WallyWorld"

@dblock and @hazendaz - should I close and create a new issue or change this issue's title?


@dblock
Copy link
Collaborator

dblock commented Jul 7, 2018

I see. You should change this issue's title and update to what you really want. I was confused because disableBasicAuthMode seems like "disable everything" for a basic auth filter, so I suggest finding a better name. And again, I personally find negaive, ie. disable-like flags a poor choice for naming because you're doing something to prevent something from happening. Like Windows where you have to press Start to shut the computer down :) So I would call things enableSomething and default it to true.

@pedroneil
Copy link
Contributor Author

@dblock thanks for challenging my options and helping me find the cause of my issue; I'll update the title and the desciption

@pedroneil pedroneil changed the title Chrome pops up login box if I type my password wrong HTTP Authentication and Authorization Failure always sending 401 Challenge Jul 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants