When a user arrives at your website hoping to use one of your services, you need to ensure 1) that they are who they say they are (authentication) and 2) that they are allowed to use the service they are trying to use (authorization).
An email-based JWT (JSON Web Token) authentication scheme can cover the first need and the resulting token can be used for the second.
If you're unfamiliar with JWTs I'd recommend checking out the excellent introduction at JWT.io. In short, JWTs provide a way to securely share information between two parties. In this case, "secure" means "hasn't been tampered with", as opposed to encrypted (we'll rely on SSL for encryption).
This authentication scheme can be broken down into a few steps for a new user:
Authorization
headerThis scheme only works if all requests are served over HTTPS
, which encrypts traffic in transit. If any requests are made over HTTP
the token will be visible to anyone inspecting web traffic and they can act as that user.
When someone tries to use our service, but doesn't yet have a token or has an invalid token, we'll need to authenticate them.
We'll be storing the token as a cookie, so when the user tries to make a request, our javascript should check for the presence of that token. If the user doesn't yet have a token, we need to ask them for their email address, which we can do in a single field form, like so:
The additional case we'll need to cover is if our user has an invalid (likely expired) token. Our backend will need to handle the token validation (more on that later). In this case, our client-side javascript sees the token containing our cookie and makes the request to our backend, which either responds with the requested data if the token is valid or a 401
if it isn't.
If we've got an invalid token, no worries, we'll just need to ask the user to authenticate again.
Once we've POST
ed the user's email address to our backend we'll want to create a JWT with a unique secret and a short expiration. We'll then send the token to the user as a link in an email that points to an endpoint for handling these single-use JWTs.
Because email isn't reliably secure so the short expiration allows us to avoid leaving the token lying around for some bad-actor to pick up and use.
When the user clicks on the link in their email, our backend will need to invalidate that token and generate a new token with a longer expiration using a new secret. After invalidating this first token, we respond to this request by redirecting the user to the desired destination, using the Set-cookie
header to save their new token as a cookie for our domain.
Subsequent requests should include the token in the Authorization
header. Endpoints that require authorization should then inspect the token and validate it using the secret associated with this user to ensure that the token hasn't been tampered with.
The user is now free to use our site password-free and we can have some confidence that the token holder is in-fact the owner of that email address. We can now use their email to determine what services that user has access to.
If you appreciate the simplicity of this auth system, you might enjoy the simplicity of bugbucket.io.
BugBucket provides public issues for private repositories, so your users can submit bug reports and feature requests to the same place that you'll resolve them.