I think it is important to consider that, to a browser, 401 initiates an authentication dialog for the user to enter new credentials, while 403 does not. Browsers think that, if a 401 is returned, then the user should re-authenticate. So 401 stands for invalid authentication while 403 stands for a lack of permission.
Here are some cases under that logic where an error would be returned from authentication or authorization, with important phrases bolded.
- A resource requires authentication but no credentials were specified.
401: The client should specify credentials.
- The specified credentials are in an invalid format.
400: That's neither 401 nor 403, as syntax errors should always return 400.
- The specified credentials reference a user which does not exist.
401: The client should specify valid credentials.
- The specified credentials are invalid but specify a valid user (or don't specify a user if a specified user is not required).
401: Again, the client should specify valid credentials.
- The specified credentials have expired.
401: This is practically the same as having invalid credentials in general, so the client should specify valid credentials.
- The specified credentials are completely valid but do not suffice the particular resource, though it is possible that credentials with more permission could.
403: Specifying valid credentials would not grant access to the resource, as the current credentials are already valid but only do not have permission.
- The particular resource is inaccessible regardless of credentials.
403: This is regardless of credentials, so specifying valid credentials cannot help.
- The specified credentials are completely valid but the particular client is blocked from using them.
403: If the client is blocked, specifying new credentials will not do anything.