The client is now able to do the following:
- Specify a password digest when creating a new user
- Query for the digest salt
This means that the client can now use the same salt and password combination to regenerate the exact same hash that it provided when creating the user.
This means that when the client wants to perform an action that requires authorization (such as updating its own profile), it can send its email and the digest to the API server, and our server will try to match them with the database records; if there's a match, the user is authenticated and the action is allowed to go ahead, otherwise, an error response is returned.
While globally carrying out this authentication process on each request would work, it is not ideal for the following reasons:
- The client would have to store the credentials locally. If this is done improperly (for example, as a cookie that has not been marked as secure), then other programs may be able to read it.
- The server would need to query the database on each request, which is a slow operation. Furthermore, it could overload the database if the API is receiving heavy traffic, making it a performance bottleneck.
Therefore, instead of providing the full set of credentials with every request that requires authorization, we should implement a Login endpoint, where our users are able to provide their password just once. After successfully authenticating themselves with the Login endpoint, the API would respond with some kind of identifier, which the client can attach to subsequent requests to identify themselves. Let's implement our Login endpoint now, and we will deal with what this identifier actually is shortly after.