Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

[Exploratory Testing] No way of distinguishing 401 vs 403 for apis. #134

Closed
harshgMSFT opened this issue Jan 26, 2015 · 18 comments
Closed
Milestone

Comments

@harshgMSFT
Copy link

Since we do not have a separate authentication phase, we do authentication and authorization while doing authorization. Since the current overloads only return a bool, there is currently no way of distinguishing between an authentication failure ( 401 ) vs an authorization failure ( 403 ).
Also read #133.

@harshgMSFT harshgMSFT added this to the 1.0.0-rc1 milestone Jan 26, 2015
@leastprivilege
Copy link
Contributor

Back in november we discussed this, that this time we want to get it right - so please do.

http://leastprivilege.com/2014/10/02/401-vs-403/

@kevinchalet
Copy link
Contributor

Related issue (in MVC): aspnet/Mvc#634 👯

@blowdart
Copy link
Member

As this came up again yesterday @HaoK, @loudej

@lodejard
Copy link

Please file a bug stating for both the cookie and bearer authn middleware: If the middleware is processing an outgoing 401, and the middleware has produced an identity for the current request, then it should change the status code to 403 and should not redirect.

@HaoK
Copy link
Member

HaoK commented Feb 1, 2015

I can take a look at making this change as part of the security auth changes, gives me an excuse to dig deeper into guts of the cookie/bearer code

@kevinchalet
Copy link
Contributor

@lodejard @HaoK hum, this change seems really weird. Why do you think the cookies or bearer middleware should be responsible of setting the response status code?

IMHO, the component responsible of doing the authorization stuff should set the 403 status code when needed. In MVC, you should change that line to use 403 when the user has been correctly authenticated: https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNet.Mvc.Core/Filters/AuthorizationFilterAttribute.cs#L34

@Tratcher
Copy link
Member

Tratcher commented Feb 1, 2015

This is an odd place to implement this. It is at the very least incomplete since something like Facebook or OIDC could convert the 401 to a redirect before getting to the cookie auth middleware, so you'd still be stuck in a loop.

Doing this centrally in the authorization layer would be less error prone than trying to handle it in the individual authentication components.

@HaoK
Copy link
Member

HaoK commented Feb 1, 2015

To be honest I agree with you as well. We know exactly in the authorize filter when to return a 403 (only after the authorize policy fails) and it's much simpler than sprinkling this 401 to 403 logic all over the various auth middlewares.

But @loudej feels strongly that this is how it should work. Perhaps we can get some insight into why this approach is better?

@blowdart
Copy link
Member

blowdart commented Feb 6, 2015

And to underscore one thing;

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 4.1) containing at least one challenge applicable to the target resource.

@Tratcher
Copy link
Member

Tratcher commented Feb 6, 2015

Having Cookie Auth generate a 403 is even stranger than I originally thought. To be consistent with the 401 scenario that redirects to LoginPath, it should redirect to a similar AccessDeniedPath if set.

@brockallen
Copy link

@HaoK
Copy link
Member

HaoK commented Feb 10, 2015

Summary of current thinking:

  • MVC Filter will always return ChallengeResult when either AuthN or AuthZ fails.
  • All security auth middlewares will have logic which knows whether it has generated an identity, on the way out, if a 401 is seen with a challenge for the identity it has generated, it will convert the 401 to a 403, and skip any other logic (redirects etc)

@kevinchalet
Copy link
Contributor

@HaoK the more I think about it, the more I realize that it's semantically incorrect:

// Simulate Authorization failure 
var result = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType);
res.Challenge(CookieAuthenticationDefaults.AuthenticationType);

It actually corresponds to a different scenario, where the user has been correctly authenticated but you want him to re-authenticate anyway. In this case, you can't alter the 401 response to return a 403 one, because the client is not supposed to try to re-authenticate.

10.4.4 403 Forbidden

The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

@HaoK
Copy link
Member

HaoK commented Mar 3, 2015

Merged 775eb5e

@blowdart
Copy link
Member

Re-opening and linking to #246

@blowdart blowdart reopened this May 20, 2015
@HaoK
Copy link
Member

HaoK commented May 26, 2015

@blowdart did you want this issue to track something different than #246 or are you just creating dupes for me to hunt down?

@blowdart
Copy link
Member

I'm creating more work now, because it's fun for me :D

@HaoK
Copy link
Member

HaoK commented Jun 3, 2015

Proposed changes are here: #273

Closing as dupe

@HaoK HaoK closed this as completed Jun 3, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants