- The store.js imports the reducers and creates the Redux store.
- Revoke the user tokens and transition the user to the Welcome scene.
- The essential boilerplate to authenticate users on your React-Native app
- If the access token is properly refreshed, the splash screen is removed and the user gets transitioned directly to the Users scene.
- POST /users : Create a new user
It’s essential to many apps, and I myself have been wondering how I could provide a secure way for my users to register and authenticate to my apps without third-party strategies. Finding working…
@ReactiveConf: The essential boilerplate to authenticate users on your #ReactJS Native app:
The essential boilerplate to authenticate users on your React-Native app
It’s essential to many apps, and I myself have been wondering how I could provide a secure way for my users to register and authenticate to my apps without third-party strategies. Finding working examples online has been tough, so I have decided to implement my own based on the few examples I could find.
The main goal of this article is to show you how to create and setup a few useful services to improve the life cycle of your app, to authenticate a user and access protected resources.
For this article I have set up a working example of a React-Native client (works for iOS and Android) and a NodeJS server on Github. Please follow the instructions from the README file to install and run the project.
The client has non-protected and protected scenes. The non-protected scenes are the ones allowing the user to login and register. Once the user is logged-in (or registered), the client receives an access token and a refresh token, and gets transitioned to the protected scene.
The access token is a credential valid for 1 hour, used for access to the protected content from the server API. When it expires, the client uses the refresh token to obtain a new access token. The refresh token is valid for 90 days, after which the user will have to manually login again.
The server is similar to the client, and has non-protected and protected entry points. The non-protected entry points require a Client ID to be sent for each requests. This ID needs to be generated ahead of time, and is sent to make sure the client is legitimate. The protected entry point requires an access token, which can be obtained by login-in.
In order for the client to be authorized to access the API you must generate a Client ID first. For the purpose of this project an open entry-point is provided to generate this ID. This should not be done in production:
parameter for each request to any non-protected entry-points.
The non-protected entry-points allow authentication and registration:
The server requires the client to send the user access token in order to make a request to the protected entry-point.
The protected entry-point allows everything else:
The application I have setup on Github uses a feature-based architecture. I would recommend you use a similar architecture to have a better organized project. I give more details about this architecture in another Medium article I wrote:
How to better organize your React applications?
I’ve been working on very large web applications for the past few years, starting from ground zero and, with a dozen…medium.com
As a reminder, this is how it’s designed:
The interface of the app is very simple. The user can access the Register or Login scenes from the Welcome scene. Once registered or logged-in, the user is transitioned to the Users scene. From there, the user can Log-out, and will be transitioned back to the Welcome scene.
Interacting with the API
The server API expects to receive a few mandatory headers for each request the client will make. It expect you to send JSON content, and returns JSON responses. Those headers are required for all requests:
We also have 2 different situations.
Of course, you don’t want to manually add those headers for every individual request you make to the server. You can create a service that will do this for you. Let’s call it the API service.
The first thing you need to do is to create a config file where you hard-code the Client ID and the URL of the server API.
I recommend you enhance this config file, as you have to use a different URL per environment, for example.
(See repo here).
We need to inject the required headers and manage the server API errors. To do that, you need to create a function that will be used for all future API requests the client will make. This function accesses the user access token and the Client-ID, and adds them to the headers as needed, so you don’t have to manually add them for each request. (see next section to learn more about session).
function for all the requests your app will make to the server API.
But you would think I should maybe create a Redux middleware to make the network calls to the server API? Keep reading.
file, suggesting that every call will have an impact on the Redux store. But this is not true. That is why I don’t use a Redux middleware.
in charge of each network request, and you import the functions wherever you need them.
Authenticate and keep the user logged-in
When you work with an app, you need to keep information about the user who requests content from the server API. The session service provides functions to authenticate and revoke user access, has its own actions and reducer to save the tokens in the Redux store and takes care of refreshing the access token automatically.
To authenticate the user, the server expects the client to send credentials via Basic Auth, transforming the email and password and adding it to the headers as Basic Access.
Once authenticated, the tokens get saved to the Redux store, and are kept on the device local storage and restored the next time the user opens the app.
A timeout is also created to automatically refresh the access token when it’s about to expire. This keeps the user logged-in when the app is open.
Logging out the user will revoke its tokens and clear them from the Redux store.
Now we’re ready to link the scenes to the different functions we’ve created.
The first thing the app does is wait for the Redux store to be restored from the last session. redux-persist allows us to save the Redux store in the device local storage and restore it later. If you wish to add a layer of security, you can also use redux-persist-transform-encrypt in order to encrypt the Redux store when saved in the device local storage. Thanks Rob Moorman for recommending this.
Once the state is ready it attempts to refresh the access token, if there is a refresh token available in the store. This is how we can auto-login the user.
If the access token is properly refreshed, the splash screen is removed and the user gets transitioned directly to the Users scene. Otherwise, the user gets transitioned to the Welcome scene.
function from the session service. If it succeeds the client transitions the user to the Users scene, otherwise, the error is extracted and displayed in the scene.
file created before.
Once a user is successfully created it gets authenticated and transitioned to the Users scene.
Revoke the user tokens and transition the user to the Welcome scene.
That’s it! You can now register and authenticate your users on your React-Native mobile app. I didn’t cover every single thing but you can access the code from Github to get to understand how everything works together.
This project is just one of many ways you can implement the authentication for your React-Native app. You can use this project as a bootstrap and adapt it for the app you want to build.
Feel free to comment below or contact me directly if you have any questions, I’ll be more than happy to help.