Today’s topic will be how we handle login to Ployst.
A Tiny Tech Overview of Ployst UI
JWT (JSON Web Tokens) is the sensible choice nowadays for implementing authentication between an SPA web application and the backend. It is a general solution for “representing claims securely between two parties”, - which means it is not just limited to our scenario depicted above, but it’s a good fit for it.
JSON web tokens are well supported in multiple languages and frameworks, which simplifies implementation. In our case, we could use out of the box solutions:
Both libraries include well documented examples on how to set them up, so it
shouldn’t be much hassle for you to get up and running. The only thing you
need to make sure is that you use consistent settings (i.e. the same prefix
for the HTTP
Authorization header, as it has different defaults in both
We won’t go into much detail here about JWT and when you should use them, you can check JWT.io should you want to dive deeper. As a few key points for our use case:
- Tokens are self-contained: the token itself can be used to encode information about the user (like username and email)
- Tokens are secure: the data is protected cryptographically to guarantee origin
- Tokens can contain an expiry date as part of the payload
- Tokens can be passed along across different services for delegated access
So a token is an attached digital signature, meaning that it contains both the data and the signature. It means you do not need to keep a record of issued tokens or session information in the server for authentication purposes.
Things we include in the token payload:
- Expiry date, after which the token is no longer valid
- Refresh expiry date, after which the token can not be renewed any more
A token can be renewed for as long as it hasn’t expired. Typically you use:
- Short lived tokens (e.g. one day or some hours)
- Longer renewal cycles (e.g. one week)
When token refresh has expired, the user will need to log in again to start a new cycle.
We want to make sure that we are not logging our users out too frequently, while still keeping the tokens short lived, so we automate the process of token renewal so that it’s to some degree transparent to the user.
The cycle of Tokens
How we use JWT in our browser SPA vs restful backend scenario:
- A user opens up Ployst
- If she has no token yet, we take notice of her intended destination and redirect her to a login page
- The user sumbits the login form, which triggers a request to obtain a token from the API
- A token is returned and stored in the browser (local storage)
- The user is then directed to the page she wanted to get to
While the user is using the UI, we handle token renewal behind the scenes:
- We periodically check for the token expiration date
- If the token is close enough to expiry, we issue a token refresh request to the API. If successful, we replace the token with the new one
- If the token can no longer be renewed, we let it expire
- When the token end of life date is reached, the user is prompted to log in again
Handling Redirect after Login in Aurelia
When a user comes to ployst after a session is expired, and they are thus redirected to a login page, we want them to be taken back to their desired destination once login is successful. That behaviour is not supported out of the box by Aurelia auth, but it’s not difficult to implement by taking advantage of Aurelia’s pipeline steps.
Aurelia auth lets you define a fixed route where users will be redirected after login. The thing we had to do was to make that destination route the one that handled the post-login redirect.
The Aurelia pipeline
Pipeline steps in Aurelia are called during the processing of a route. They would be the front-end equivalents of Django middleware.
Authentication in Aurelia is already handled as a pipeline step. We added an extra step that runs before authentication, to take care of storing the next URL.
This is an excerpt of our
aurelia-auth configuration parameters:
And finally these are the relevant bits of our
login-redirect view model: