Subject: HTTP Status Codes 401 and 403

From: Grant Gryczan <[email-masked]>
Date: Sun, 10 Jun 2018 18:36:11 +0000

Hello,

I have a significant question on the HTTP specifications for 401 Unauthorized <https://tools.ietf.org/html/rfc7235#section-3.1> and 403 Forbidden <https://tools.ietf.org/html/rfc7231#section-6.5.3> on the topic of authentication and authorization.
For 401, it states that the "request has not been applied because it lacks valid authentication credentials for the target resource", and that, if "the request included authentication credentials," then "authorization has been refused for those credentials."
This implies to me a few things in particular: 401 can be returned if the credentials are invalid or expired, 401 can be returned if the credentials do not suffice the particular resource, and 401 can be returned if credentials are required but unspecified.
For 403, it states that, if "authentication credentials were provided in the request, the server considers them insufficient to grant access", and that the "client MAY repeat the request with new or different credentials."
This also implies to me a few things in particular: 403 can be returned if the credentials are invalid or expired, 403 can be returned if the credentials do not suffice the particular resource, and 403 can be returned if credentials are required but unspecified.
The implications to me seem the same.
Obviously 403 is different in that it can also be returned if the issue has nothing to do with authentication, but, other than that, what is the effective difference under the context of authentication?
Here are a few cases I would really appreciate to also be clarified in particular as to whether 401, 403, or something else should be returned and why. (I bolded all the important words for you too!)
A resource requires authentication but no credentials were specified.
The specified credentials are in an invalid format. (I expect 400, but I'm just making sure.)
The specified credentials specify a user which does not exist.
The specified credentials are invalid but specify a valid user (or don't specify a user as a specified user is not required).
The specified credentials have expired.
The specified credentials are completely valid but do not suffice the particular resource.
The particular resource is inaccessible regardless of credentials. (I expect 403.)
The specified credentials are completely valid but the particular client is blocked from using them.
Any other relevant cases you can think to clarify would also be appreciated, and you may tell me if you would like clarification from me on any of the above cases or information as well.
I have researched all of this information very thoroughly, but all of the answers vary greatly and contradict the spec, themselves, and/or other answers.
I hope you find the time to clarify this and will be looking forward to your response, as this problem is very important to me and to many others.

Thank you for your valuable time and consideration,
Grant Gryczan

---

From: Philipp Junghannß <[email-masked]>
Date: Mon, 11 Jun 2018 15:12:42 +0200

it's probably partially also a subjective thing because of the overlap but
consider the current browser behavior in regards of authentication, at
least for user-facing sites.
401 spawns an auth dialog while 403 does not.

considering that I persobally would go through your list as follows:

   - A resource requires authentication but *no credentials* were
   *specified*.

obviously 401 as we want the user to authenticate.

   - The specified credentials are in an *invalid format*. (I expect 400,
   but I'm just making sure.)

I would also go with a 400, unless there's a reason to choose something
else before that (e.g. server errors, redirects and so on)

   - The specified credentials specify a *user* which *does not exist*.
   - The specified *credentials* are *invalid* but specify a valid user (or
   don't specify a user as a specified user is not required).

The above 2 points I would put together as they are very often brought
together.
as in both cases we want the user to reauthenticate 401 on both would be
appropriate.

   - The specified *credentials* have *expired*.

This is a tricky one to be honest, I would also spawn a 401 as I can see
that these credentials are kinda useless.

   - The specified credentials are completely valid but do not *suffice* the
   particular *resource*.

I would say, if there's a chance the user can provide sufficient
credentials (for example multiple credentials for different access levels)
go with 401, otherwise just use 403

   - The particular *resource* is *inaccessible* regardless of credentials.
   (I expect 403.)

obviously I agree. 403 all the way.

   - The specified credentials are completely valid but the particular
   *client* is *blocked* from using them.

This one isnt easy in my opinion as well. If the client is completely
blocked from using any credentialy, just drop a 403, otherwise you would
need to think about whether or not you want to expose the possibility of
other credentials being usable on that client before deciding 403 or 401.

for non-User-facing-sites (APIs for example) it gets a bit more ugly as you
cant use browser behavior for your decisions but I wouldnt change most of
them

I would first say that in all cases where you can drop the credentials
entirely (user doesnt exist, wrong credentials of valid user, expired) drop
a 401 (depending on how secret/secure you want, add a message)
for other cases where the credentials do leave a valid authentication but
that the user shall not pass regardless drop a 403 and throw a message
along for example in the body as JSON (or whatever format your API works
with), so the programmer of any API client can deal with those messages and
decide what to do.

As said all of this is my pure opinion on this and no authorative
information whatsoever,

Regards.

Am Mo., 11. Juni 2018 um 14:46 Uhr schrieb Grant Gryczan <
[email-masked]>:

> Hello,
>
> I have a significant question on the HTTP specifications for 401
> Unauthorized <https://tools.ietf.org/html/rfc7235#section-3.1> and 403
> Forbidden <https://tools.ietf.org/html/rfc7231#section-6.5.3> on the
> topic of authentication and authorization.
> For 401, it states that the "request has not been applied because it lacks
> valid authentication credentials for the target resource", and that, if "the
> request included authentication credentials," then "authorization has
> been refused for those credentials."
> This implies to me a few things in particular: 401 can be returned if the
> credentials are invalid or expired, 401 can be returned if the credentials
> do not suffice the particular resource, and 401 can be returned if
> credentials are required but unspecified.
> For 403, it states that, if "authentication credentials were provided in
> the request, the server considers them insufficient to grant access", and
> that the "client MAY repeat the request with new or different credentials."
> This also implies to me a few things in particular: 403 can be returned if
> the credentials are invalid or expired, 403 can be returned if the
> credentials do not suffice the particular resource, and 403 can be returned
> if credentials are required but unspecified.
> Obviously 403 is different in that it can also be returned if the issue
> has nothing to do with authentication, but, other than that, what is the
> effective difference under the context of authentication?
> Here are a few cases I would *really* appreciate to also be clarified in
> particular as to whether 401, 403, or something else should be returned and
> why. (I bolded all the important words for you too!)
>
>    1. A resource requires authentication but *no credentials* were
>    *specified*.
>    2. The specified credentials are in an *invalid format*. (I expect
>    400, but I'm just making sure.)
>    3. The specified credentials specify a *user* which *does not exist*.
>    4. The specified *credentials* are *invalid* but specify a valid user
>    (or don't specify a user as a specified user is not required).
>    5. The specified *credentials* have *expired*.
>    6. The specified credentials are completely valid but do not *suffice* the
>    particular *resource*.
>    7. The particular *resource* is *inaccessible* regardless of
>    credentials. (I expect 403.)
>    8. The specified credentials are completely valid but the particular
>    *client* is *blocked* from using them.
>
> Any other relevant cases you can think to clarify would also be
> appreciated, and you may tell me if you would like clarification from me on
> any of the above cases or information as well.
> I have researched all of this information very thoroughly, but all of the
> answers vary greatly and contradict the spec, themselves, and/or other
> answers.
> I hope you find the time to clarify this and will be looking forward to
> your response, as this problem is very important to me and to many others.
>

---

From: Michael Sweet <[email-masked]>
Date: Mon, 11 Jun 2018 11:38:32 -0400

My (totally IPP/CUPS-centric) opinion on the valid credentials but no access case is below... (but otherwise I agree with Philipp's responses)

> On Jun 11, 2018, at 9:12 AM, Philipp Junghannß <[email-masked]> wrote:
> ...
> 	• The specified credentials are completely valid but do not suffice the particular resource.
> I would say, if there's a chance the user can provide sufficient credentials (for example multiple credentials for different access levels) go with 401, otherwise just use 403

For CUPS we use (and IPP recommends) 403 since you *have* authenticated successfully and cannot proceed further.  Because browsers won't show an authentication dialog for a 403, it makes things very clear to the user/agent that the authentication succeeded but they have no access with those credentials.  If you keep returning 401 then the user agent will keep presenting UI and the user will become frustrated trying to figure out what the right username or password is, possibly leading to their account getting locked if the underlying auth mechanism has retry limits...

Depending on how paranoid your implementation needs to be, your 403 response can also include helpful text ("User XYZ does not have access privileges.", etc.) that the browser (may) display.  But the important thing is to stop unhelpful authentication dialogs that lack the context needed for a user (or user agent) to determine what is happening.

_________________________________________________________
Michael Sweet, Senior Printing System Engineer

---

From: Philipp Junghannß <[email-masked]>
Date: Mon, 11 Jun 2018 23:35:17 +0200

Michael's reply is totally true as well, which is why I said "if you can
expect the user to have some other credentials". on cups I think most users
probably dont have multiple credentials so 403 absolutely makes sense.

also regarding an error page, an authentication can also show some text the
site chooses, where it could say something along the lines of "You dont
have access but you can try as a different user" or whatever.

generally speaking, in my opinion we may need a few more codes those
use-cases.

Am Mo., 11. Juni 2018 um 17:47 Uhr schrieb Michael Sweet <[email-masked]>:

> My (totally IPP/CUPS-centric) opinion on the valid credentials but no
> access case is below... (but otherwise I agree with Philipp's responses)
>
> For CUPS we use (and IPP recommends) 403 since you *have* authenticated
> successfully and cannot proceed further.  Because browsers won't show an
> authentication dialog for a 403, it makes things very clear to the
> user/agent that the authentication succeeded but they have no access with
> those credentials.  If you keep returning 401 then the user agent will keep
> presenting UI and the user will become frustrated trying to figure out what
> the right username or password is, possibly leading to their account
> getting locked if the underlying auth mechanism has retry limits...
>
> Depending on how paranoid your implementation needs to be, your 403
> response can also include helpful text ("User XYZ does not have access
> privileges.", etc.) that the browser (may) display.  But the important
> thing is to stop unhelpful authentication dialogs that lack the context
> needed for a user (or user agent) to determine what is happening.
>