Implementing an Authentication Flow Part 1: Initial Design

Introduction

This series of article presents a way to perform authentication flow in a React-Native application using Redux, Amazon Web Services (AWS), and multiple authentication providers. While React-Native& Redux are used in this article, the principles applied here should work for multiple different languages across multiple environments.

In a previous post, I presented one method to show a pop up menu. One of my purposes for that menu was to present a “Sign In” button to the user. Pressing this button tells my simple navigator to go to the application’s sign-in screen that presents the user with the option to login using a social network or the Auth-0 authentication service. This series of articles will step through the entire process; from creating the UI using react and Expo.io to logging in using multiple authentication services.

This series of posts has 5 parts:

  1. Implementing an Authentication Flow Part 1: Initial Design

2. Creating the UI & AWS API Gateway and Lambda Integration

3. Social Login in React Native + Expo.io and AWS API Gateway + Lambda Authentication

4. Caching Google and Facebook Login Authentication Data Locally in a React-Native & Redux Application

5. User Name and Password Login Using Auth0 in an Expo.io + React Native Application

Design

Using React-Native puts me in a gray area as far as which APIs to use. My eventual goal is to build a native application using React-Native; however, I think of React-Native as more of a web application since I’m not using native APIs provided by whatever service I’m using. On the other hand, I can’t rely on JavaScript APIs because they may work based on access to objects that only exist in the browser like window. The bottom line is that while some authentication services expose native APIs for Android and iOS, and may have JavaScript APIs, I always default to using simple HTTP endpoints when those are available. These endpoints are often protected, and the Expo Facebook and Google APIs expose methods that allow me to obtain an access token that lets me use those HTTP endpoints assuming the user successfully signs in to the service.

Upon successful signup, authentication services return something. The exact contents of that something varies between services. However, all the services I’ve used provide some sort of access token enabling user verification. I think of the token as a temporary ID card that my application can show to authentication provider to confirm that the person using my application is actually who they say they are. Think of the application as someone trying to get into a bar, and the authorizer as a bouncer.

“You need a valid access token to get to this API”

Authentication Flow Steps

A flow based on the metaphor results in the following steps:

1. User has an ID and wants me to perform some action

2. User passes me the ID

3. I give the ID to the original issuer

4. Original issuer confirms that the ID is valid

5. I perform the requested user action

In my application this corresponds to:

1. User logs in to authentication service via the application sign in page

2. Application receives information from service, including access token

3. User tells application to perform an action that I determined requires authentication. For example, save an image to the server.

4. Application passes that request to an authorizer that safely resides on my server away from any malicious actors who only have access the application. Additionally, the access token is passed with the same request.

5. The authorizer receives the request and access token.

6. Authorizer passes the access token to the authorization service which checks the token’s validity and responds.

7. Based on that response, the authorizer either tells my application

“No, I’m not going to do this because your token was invalid so I’m not sure you’re really who you say you are”

or

“Yes, your token was valid, and since the service vouched for you, I’ll do what you want me to do”

Of course, the application isn’t going to speak plain language, but hopefully, this conveys the idea. The animation below also conveys the authentication flow.

So far, I’ve mentioned the authorizer a couple of times so I should probably explain it. An authorizer is a function with the following characteristics:

1. Inputs:

a. Receives takes the authentication information desired by authentication provider as an input. This is typically the access token.

b. Receives the desired action to performed as an input

2. Functionality:

a. Passes the access token to the authentication provider.

b. Receives the validity of the token from the authentication provider

i. The authentication service may respond with information that indicates that the token is:

1. Valid

2. Invalid

3. Expired

4. Something else depending on the provider

c. Based on the authentication provider’s response, the authorizer performs the desired action or sends a response to the application indicating it won’t perform the action, and why.

Tools

In addition to React-Native, Redux, and AWS, my application uses the Expo.io framework. Expo exposes APIs for Google and Facebook authentication. Not only are those flows covered in the documentation, Expo presents examples of how to use each at https://snack.expo.io. The Snack web application lets a user drag and drop components into a React-Native application. I created a “snack” with Facebook login functionality here https://snack.expo.io/BkNljxMxb. This application presents the user with the usual login with Facebook flow which is covered here https://developers.facebook.com/docs/facebook-login/web. Successful authentication with the Facebook login service returns authentication and user ID information that can be used later.

Amazon Web Services

Implementing this plan requires not only an application that the user interacts with, but server functionality to securely authenticate with the authentication providers. While one could verify authentication from the client’s device, there’s nothing stopping a malicious client from “vouching” for themselves by posting fake information or playing with messages passed to your API.

Does this look like a trustworthy user to you?

Of course dealing with a server comes with its own problems. To avoid some of the issues with spinning up and maintaining a server, I’ll be using Amazon Web Services’ API Gateway and Lambda functions as the backend. In fact the authorizer mentioned above will be a Lambda function.

The flow for a valid authentication token is shown below. It shows where Lambda and API Gateway fit in.

Authentication Flow for Approved User

On the other hand, an invalid access token will result in the following flow.

Authentication Flow for Unapproved User

In the next post, I’ll discuss how I actually implemented everything presented here.

Reginald Johnson has maintained his passion for coding throughout his 20+ year career as an Officer in the United States Navy. He enjoys applying his training and experience in programming, Systems Engineering, and Operational Planning towards programming. Follow him Twitter @reginald3.