With Every App Comes Authorization
Recently I was faced with a reality that it is the time to introduce authorization to my Pomodoro web app. By the current moment, I implemented authorization six times and not very excited about doing this routine task, and I think you too. So let’s make it as fast and easy as possible.
Broken Hope: AWS Cognito
Recently I heard about a magic AWS service — Cognito that makes authentication in your app super simple. Since I already had quite an experience working with AWS, I decided to give it a shot. It took me much more time than I expected and I was discouraged by the fact that this service doesn’t save the user’s email and name from Google/Facebook. And this is SUCKS, so I gave up on this service.
In this story, we will cover both the front-end and back-end parts. Front-end bootstrapped with create-react-app. If you are interested in steps to made in newly created React app to add redux and redux-saga you can check this story. If you want to dig in the source code, you can explore this repo. The back-end is written on NodeJS and using Apollo Server, but we will look at parts that can be reused regardless of the technology.
Authentication flow will look this way:
- Receive a token from Google/Facebook.
- Make a request to the back-end to receive JWT token.
- Save token to local storage and use it in requests to back-end until it expires.
For authentication, we will create a simple component with two buttons.
When a user clicks on one of the buttons appropriate saga will be triggered. Both of them are very similar and have the same steps.
First, we need to load the script if not loaded. We will write the function to do this.
When a provider’s code in place we are calling one of its methods for authorization and pass scope that specifies what user’s data we want, in our case it is email and basic user info.
And of course, we need to get keys to make requests to Google and Facebook and specify them in constants.
With a token from the provider, we are ready to make the request to our app and authorize a user.
In this function, we build a query for GraphQL backend where we specify the name of provider and token. Then we trigger action to save response in the state.
We can save token to local storage in redux middleware like this.
By taking a token from local storage, we can make a request to the API.
I think we covered the main parts of the authorization process on front-end. Now let’s look at what is going on on the back-end.
We will not go into specifics here but rather will look at parts that can be reused regardless of the technology you use.
First, let’s write a function that will receive the name of the provider and token and return user and auth data. Also, this function will save user to the database if no such user exists.
Here we are using quite a few utility functions for authorization. Let’s list them here.
To provide userId to the context of a request, we will take a token from headers, validate it and take userId from it.
For Medium readers, I provide a Udemy course How to Start React Project: Best Practices for 9.99$. The goal of this course is to share with You my findings of the last few years about what steps and decisions are better to make at the beginning of development so that you will have a good starting point for your new project.
Reach the next level of focus and productivity with increaser.org.