Frontend development with React.js for OIDC controlled API access

Thomas Scherer
6 min readApr 5, 2021

This is the last tutorial of the series to build full stack CRUD applications using API backend and API management on Kubernetes. Here we will add the last piece, which is the actual frontend to consume the API.

The overview of the tutorial series is shown here:

In this part we will develop a React.js based web application in Visual Studio code, we will wrap it in a docker container and deploy it onto the Kubernetes cluster. The App will redirect to the access manager for login, and if successful consume the API.

What you will need to run this tutorial

  • Visual Studio Code
  • The result of previous tutorials, i.e. a webapi, an API gateway and an OIDC capable access manager
  • Basic knowledge of React

Here I would like to recommend the step-by-step tutorial of React to obtain basic knowledge of React. I find it really intuitive and easy to learn:

We will use material-ui to let our Webpage look nice (ignoring my poor artistic capabilities). The library is well documented here:

The resulting code of this tutorial can be found here:

Setup of a React App in Visual Studio Code

Open up Visual Studio code and launch a terminal. Run following commands to install React and required modules to run the code

npx create-react-app carlibraryviewer
cd carlibraryviewer
npm install @material-ui/core
npm install @material-ui/icons
npm install axios
npm install react-router-dom
npm start

Aside to material-ui, we install axios to interface the backend API. React-router-dom is required here in two manners:

  • To handle authentication and involved browser redirections and access to browser state information
  • To actually reflect menu structure in URLs

Handling environmental variables for later containerization

Just like in the initial tutorial for .NET 5.0 we want to ship the resulting code in a docker container, in such way, that we can set parameters using environmental variables. That way, we can inject variable parameters as part of the yaml file of the pod deployment.

Visual Studio Code allows changes within the javascript code during nodejs runtime. It’s worth to node that those environmental variables are solely read during launch time. If those are changed then you need to restart npm.

Environmental variables can be specified in an “.env” file in the project root folder. Here we will need such file to carry all information relative to our Gravitee configuration:

  • REACT_APP_API_URL: This is the root URL of the API to be consumed
  • REACT_APP_OAUTH_URL: Here we put the URL of the authorization gateway to which we redirect for login =https://authorize.toms-lab.net/carlibraryauth
  • REACT_APP_OAUTH_CLIENT_ID: The client ID, which the access manager needs to properly link the application
  • REACT_APP_OAUTH_CLIENT_SECRET: The Base 64 encoded concatenation of clientId + ‘:’ + :clientSecret

All those parameters (except API path) can be copy pasted from the overview page of your Gravitee AM application definition:

If you use an external identity provider, then you will get that information from there. Here is the .env file for my example

Code the React application

Here is my code, which should be easy to understand if you managed the step-by-step tutorial of reactjs.org:

Nonetheless, here some noteworthy points:

As you will see, there’s an <Authenticate> component, which implements the OIDC login flow. The flow is as follows:

  • Step 1: Unauthorized access to the webpage
    Identified by: state.tokens variable==null
    Action: Render <Login> component
  • Step 2: Login component is started but no access code for user
    Identified by: no code param in URL && state.code==null
    Action: Redirect to login page (to obtain code)
  • Step 3: User returns from login page after successful login
    Identified by: Code param in URL && state.code!=null
    Action: Cleanup URL i.e. set URL before login
  • Step 4: We are back on the good URL and have a code
    Identified by: No Code param in URL && state.code!=null
    Action: Contact access manager via axios to obtain bearer token

The resulting bearer token is passed as props variable to all inner components to interface the API with bearer token set. Additionally the scope variable is seen so that we can disable controls if the “write” scope is missing (which we defined in previous tutorials to implement the admin role). You may change the isAdmin() function to simply return true, to validate that the API gateway is controlling administrative access. It will return access denied if you use user “John” of previous tutorials.

One final important statement. MainView.js implements the main page skeleton with Menu. Make sure you use ‘react-router-dom’ Link component for those URLs to support lazy loading. Otherwise you will lose all state including tokens and login will be restarted. Aside to speed, this is transparent to the user since his session is still active on the access manager, and so a code is generated without additional login. Yet, it will increase the amount of requests on the access manager.

import Link from ‘react-router-dom’;
//import Link from ‘@material-ui/core/Link’;

In previous tutorial, we configured access manager to allow localhost redirection. Hence you may build and test your code locally.

Package in container

Once the code is ready and working you can as in initial tutorial create a Dockerfile:

Open the command palette (⇧⌘P or shift-ctrl-p), click “Docker: Add Docker Files to Workspace…”. Follow instructions.

Answer questions (platform: nodejs, Package file package.json).

The resulting Dockerfile will have below commented RUN command, which does not work for me since npm fails to find the node modules. If it is the same for you, then just remove “&& mv node_modules ../”

#RUN npm install --production --silent && mv node_modules ../
RUN npm install --production --silent

Now you can build your image:

Open the command palette (⇧⌘P or shift-ctrl-p) > Docker Images: Build Image …

As in the first tutorial you may push the resulting image to Docker Hub to later retrieve by the Kubernetes Cluster: Under the docker tab in Visual Studio Code you can configure access to your docker repository like Docker Hub. Right-click the image and click “Push…” to upload the image (your namespace is your user name on docker hub).

Now it’s time to deploy on Kubernetes. This should be familiar meanwhile. Here is an example yaml file containing service, pod and ingress including all environmental variables, which we defined for the application:

Deploy as before

kubectl apply -n carlibraryapi -f carviewer.yaml

The webpage should redirect you to the login page. Afterwards you should be able to see and change the data in the postgres database, which we deployed back in tutorial 1.

--

--