Developer Toolbox
4xx client errorRetry with credentialsHeader: WWW-Authenticate

401 Unauthorized

The request has no valid credentials for the resource. Despite the name, 401 is about authentication (who you are), not authorization. The server has to say how to authenticate, in a WWW-Authenticate header.

Open JWT Decoder Decode the token and check its exp, aud and iss.

Common causes

  • No Authorization header at all, often because a proxy or a redirect dropped it on the way.
  • The token expired: its exp claim is in the past, or the clock on one side is off.
  • The token was issued for another API: its aud or iss claim isn't what this server expects.
  • A header the server can't read: a scheme it doesn't accept (Basic where it wants Bearer), or a token that picked up a quote or a line break on the way.
  • The key that signed the token was rotated, and the server no longer trusts it.

How to fix it

  • Decode the token and check exp, aud and iss before anything else.
  • On an expired access token, refresh it once and retry. If the refresh fails too, send the user to log in again instead of looping.
  • Check that the header survives the trip. Most clients drop Authorization on a redirect to another host, and so does curl -L unless you add --location-trusted.
  • Read WWW-Authenticate: it names the scheme and often the reason, such as error="invalid_token".

401 or 403?

401 means "I don't know who you are": send credentials, or refresh the token. 403 means "I know who you are, and the answer is no": retrying with the same identity won't help.

Example

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="The access token expired"
Content-Type: application/json

{"error": "invalid_token"}

Defined in RFC 9110, section 15.5.2.