This PR completely overhauls how login/authentication/authorization is done via this application.
We were previously using JWTs for login/auth, but we had a mono-api which handled requests and serving webpages.
We have recently parted out two applications, a react UI and a backend api.
With this in place the auth flow needs to look different.
This PR updates the auth flow from the UI to API, according to best practices.
Design decisions
When a user is logging in, they send their credentials to the API (/auth/login). These credentials, if valid, result in the user receiving an access_token (and some other info).
How the UI handles storing (or not storing) this access_token was the single biggest question that had to be answered when creating this PR.
The naive approach is to store this access_token via local storage (in the User's browser) or as an insecure cookie.
This way, the UI could always fetch it whenever it needed to make another API request.
However, storing these details in the browser via javascript was deemed insecure by the community, as any maliciously running javascript in the browser could fetch this token and then proceed to pretend to be the user.
So instead of this, I had to do a ton more work, which includes storing that token via react context, handling the scenarios where, once the browser is refreshed, react context is cleared, and I now need a way of retrieving a new access_token (WITHOUT forcing the user to sign back in) - this is done via "refresh tokens" - and is actually pretty clever.
I have a good understanding of access_tokens and refresh_tokens, but there was one tutorial in specific that I pulled code snippets and ideas from that would have taken me much longer to reverse engineer and implement myself:
Description
This PR completely overhauls how login/authentication/authorization is done via this application.
We were previously using JWTs for login/auth, but we had a mono-api which handled requests and serving webpages.
We have recently parted out two applications, a react UI and a backend api.
With this in place the auth flow needs to look different.
This PR updates the auth flow from the UI to API, according to best practices.
Design decisions
When a user is logging in, they send their credentials to the API (/auth/login). These credentials, if valid, result in the user receiving an
access_token
(and some other info).How the UI handles storing (or not storing) this access_token was the single biggest question that had to be answered when creating this PR.
The naive approach is to store this access_token via local storage (in the User's browser) or as an insecure cookie.
This way, the UI could always fetch it whenever it needed to make another API request.
However, storing these details in the browser via javascript was deemed insecure by the community, as any maliciously running javascript in the browser could fetch this token and then proceed to pretend to be the user.
So instead of this, I had to do a ton more work, which includes storing that token via react context, handling the scenarios where, once the browser is refreshed, react context is cleared, and I now need a way of retrieving a new access_token (WITHOUT forcing the user to sign back in) - this is done via "refresh tokens" - and is actually pretty clever.
I have a good understanding of access_tokens and refresh_tokens, but there was one tutorial in specific that I pulled code snippets and ideas from that would have taken me much longer to reverse engineer and implement myself:
https://youtu.be/27KeYk-5vJw?si=A1HTG7PAMf7Yv56U