User authentication is the interaction that confirms a user's identity between a human and a machine. It allows the machine to determine whether the user has the correct access rights and identity.
We implemented Cloud SQL with great success on a recent project which you can read about here. But unlike Firebase, which has an ‘out-of-the-box’ solution for user authentication, we needed to explore something a little more in-depth for Cloud SQL.
We decided to approach the problem using JWT’s (https://jwt.io/).
JWT stands for JSON Web Token. It is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
The client would send a JWT in the ‘Authorization’ header when a relevant url required it. We then verify the token and ensure that user should be able to access the related resource.
Creating a JWT
The first challenge then is - how does the client get a token? To create a token you need to use a private key and, therefore, it’s not something you want to share around. Ideally, we want to create the token on the server and pass it to the app. We do this in the form of a login API:
In this API we take the user’s email and password (in the form of a hash) and verify them against our user table. We then use a JWT token library to help us create a token which encodes all the information we require when it comes to reading it back in.
And return that token to the user.
The public and private keys should look something like this:
Note also that we are using a password hash since it’s good practice not to store a user’s actual password in your backend.
Verifying a JWT
Now the client has a token (which they can store locally). They then add this into the header for a request. To verify a token within an API, we also make use of the JWT library which offers a nice mechanism of verifying:
As you can see from above, there are two different ways you can verify a token. Either using the JWT library and creating a JWTVerifier, which has many options for more complex verifications. Or you can get the data out of the token (jwt.getClaim("id").asString()) and verify it yourself directly.
Best before date
It is also worth noting that using an expiry date with JWT’s is also very common. Meaning that the client would need to keep calling the login url to get a fresh token. This would mean that if someone got hold of your token it would only allow access to the resource for a finite period of time.