401 vs 403

Après avoir débattu de ce sujet, je me suis rendu compte qu’il n’existe aucune explication claire et précise sur l’utilisation de ces codes HTTP. Sur des tentatives on peut lire « à mon avis » ou encore « selon mon interprétation »… mais il n’y a ni lieu d’interpréter, ni même lieu à débat, comme nous allons le voir.

Avant tout…

Il va falloir bien faire la différence entre deux notions : l’authentification et l’autorisation.

Authentification

L’authentification est la vérification de l’identité. Lorsque vous rentrez votre login et mot de passe sur un site, vous affirmez être un certain utilisateur avec votre login, et le mot de passe est utilisé pour vérifier que vous êtes bien cet utilisateur. Ces deux informations permettent entre autres d’attester de votre identité. On peut y référer en anglais sous le terme « credentials » (« identifiants » en français).

Autorisation

L’autorisation est le fait de déterminer si une ressource est accessible ou non. Il est très important de comprendre que l’autorisation est indépendante de l’authentification car on a pas forcément besoin d’identifier quelqu’un pour l’empêcher ou non d’accéder à une ressource.

On peut commencer

401

L’authentification HTTP est spécifiée dans la RFC 7235 qui définit le code de statut 401. La première chose à noter, c’est qu’on ne parle pas de n’importe quelle authentification : on parle d’authentification HTTP, où les identifiants sont demandés via le header WWW-Authenticate et fournis via le header Authorization. Elle provoque notamment l’affichage de ce genre de message dans un navigateur :

Le serveur requiert un nom d'utilisateur et un mot de passe.

Quand vous remplissez le formulaire de connexion d’un site, vous êtes donc hors du contexte de cette RFC et n’avez aucune raison de recevoir une 401.

Maintenant voyons justement ce que nous dit cette dernière.

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.

If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials. The user agent MAY repeat the request with a new or replaced Authorization header field (Section 4.2). If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user agent SHOULD present the enclosed representation to the user, since it usually contains relevant diagnostic information.

J’ai surligné ci-dessus les causes de retour d’une 401 :

  • La requête ne contient pas les identifiants nécessaires à l’accès à la ressource.
  • Les identifiants de la requête n’ont pas permis l’accès à la ressource (généralement parce qu’ils sont faux).

Notez que si le nom du statut est « unauthorized », c’est parce que si une condition à l’accès d’une ressource est l’authentification, alors l’échec de l’authentification entraîne le refus de l’autorisation.

Au final si vous n’implémentez pas un système d’authentification HTTP, vous n’avez aucune raison de retourner une 401.

403

La description de ce code de statut se trouve dans la RFC 7231 :

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).

J’ai encore une fois surligné la cause de retour : le serveur n’autorise pas la requête. C’est tout !

Si une 401 n’a pas déjà été retournée et que vous devez interdire l’accès à une ressource, il faudra donc retourner une 403.

Notez juste qu’un accès refusé n’est pas forcément synonyme d’interdiction ; comme stipule le dernier paragraphe vous pouvez vouloir cacher l’existence de la ressource en retournant une 404, ou rediriger l’utilisateur vers un formulaire de connexion si nécessaire.