Auth token management with Node.js Observer pattern
Consider the following situation where you are getting data from a third party server using the authentication token.
- You request the auth token
- Auth token received.
- Send request with auth token
- Received the desired response.
And once the token expires, we fetch a new one, save it and keeps on making this new request with this new auth token.
Here is the sample code with for request.
Below is our mocked authentication system
Now if we run both apps on respective port (8080 and 8081), and run this test script
we would received the following logs at the services as expected
// serviceHandler output
{“newToken”:”def”}
No need for new request
No need for new request
No need for new request
No need for new request
No need for new request
No need for new request
No need for new request
No need for new request// Token generator output
I am handling token: abc
Lets go ahead and modify our test script to run the curl commands in parallel. This simulates multiple incoming request to your node server.
And the output this time???
// serviceHandler.js{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}
{"newToken":"def"}// tokenGenerator
I am handling token: abc
I am handling token: abc
I am handling token: abc
I am handling token: abc
I am handling token: abc
I am handling token: abc
I am handling token: abc
I am handling token: abc
I am handling token: abc
As you can see from the output, all request were made in parallel and all ended up calling the auth service.
Wouldn’t it be nice if only one request was made to the auth service for getting the new token while other request wait for token generation to be completed. Once the authentication is completed, it should notify the other requests to use the new token and start working.
Welcome Observer pattern. So this should the workflow should look like
- If we have an invalid token, update a variable to represent that we are in the middle of getting new token.
- Make an actual request for the new token.
- Once the request is completed successfully, unset the variable to show that no request for auth is in progress.
- Send an event that new token is available so that other listeners can take appropriate action.
Step 1,2 and 3 are easy. We can maintain a global variable/state in Redis which request can check before making a new request.
Lets implement step 4: Lets start with our Observable code
Now we have to do it listen to done
event and we are good. Something like this
Running the same test script would give the below output
// betterServiceHandler
{"newToken":"def"}// tokenGenerator
I am handling token: abc
As we can see, we only called the token generator service only once!
UPDATE:
As noted by Hoseong Asher Lee, we should use observable.once
instead of observable.on
as mentioned in the blog. This would make sure an event handler is called only once