How to Run the React SPA

Background

Previously we provided a Final SPA Overview and next we will show how to run the Final SPA on a Developer PC in a couple of different configurations.

Prerequisites

The scripts in this post are meant to be run from a Linux or macOS terminal, or a Git Bash shell on Windows. You also need to have an up to date version of Node.js installed.

Step 1: Download the GitHub Code

The SPA project is available here, and can be downloaded / cloned to your local PC with this command:

git clone https://github.com/gary-archer/oauth.websample.final

Step 2: Add Domains to your Computer

You will need to ensure that this blog’s web development domain points to your local PC, by making a local DNS entry in your hosts file, which will exist at one of these locations:

OS Path
Windows c:\system32\drivers\etc\hosts
macOS / Linux /etc/hosts

Add entries as follows to represent the domain that serves the SPA’s static web content:

127.0.0.1  localhost web.authsamples-dev.com
::1        localhost

Step 3: View Components in an IDE

The web code consists of the following main areas:

Component URL(s)
spa The code for the SPA, which calls cross domain APIs using secure cookies
webhost A simple web host to use in local computer setups, to serve web static content to the browser
cloudfront-extensions Extensions used when the web host is the AWS  content delivery network
deployment Resources used for managing and automating various deployment scenarios

Step 4: View the React Code

The SPA has been updated to use React, though view classes have the same behavior as those from Earlier SPA Code Samples:

export function TitleView(props: TitleViewProps): JSX.Element {

    return  (
        <div className='row'>
            <div className='col-8 my-auto'>
                <HeadingView />
            </div>
            {props.userInfo &&
                <div className='col-4 my-auto'>
                    <UserInfoView {...props.userInfo}/>
                </div>
            }
        </div>
    );
}

React provides a modern toolset that will helps to enable productivity and capabilities for web development:

Benefit Description
Markup A strongly typed and secure way to work with markup and the DOM, including handling of dangerous input
Components A componentized development model, that promotes clean code and a separation of concerns
Ecosystem We can follow web development best practice techniques from the community

Step 5: Build the Code

Open a terminal and run the following command. The script builds the SPA into JavaScript bundles and prepares a basic web host to serve them as static content:

./build.sh

This runs the frontend in watch mode, so that it can be developed with a pure SPA development model. The React code can be updated and changes quickly reflected in the browser:

Step 6: Configure SSL Trust

The build script downloads some development certificates:

To make the browser trust the certificate’s issuer you need to import the authsamples-dev.ca.pem root certificate into your Browser’s Trust Store:

Step 7: Run the App

Next start a second terminal window and run the following command, which will start the web host, then invoke the default browser at https://web.authsamples-dev.com/spa/:

./run.sh

Step 8: Login to the SPA

You will then be prompted to sign in, and can do so with this test credential:

  • User: guestuser@mycompany.com
  • Password: GuestPassword1

The SPA will then get data from a remote API hosted behind the AWS API Gateway. The SPA will then render its simple views:

Step 9: View Secure Cookies

The SPA no longer uses tokens and instead uses only the strongest cookies. When run on a development computer, it uses these cookie properties:

  • HTTP Only
  • Secure
  • SameSite=strict
  • Domain=api.authsamples-dev.com
  • Path = /
  • AES256 Encrypted

You can use browser tools to view secure cookies issued, which are for the API subdomain and not the web origin. The SPA does not require any cookies to download static content, and does not use cookies when the user performs navigation operations:

Step 10: View Updated SPA Configuration

In earlier samples, the SPA performed its own OpenID Connect work in JavaScript. This work is now done by remote token handler components, and the SPA code and configuration is therefore simplified:

{
    "apiBaseUrl": "https://api.authsamples-dev.com/tokenhandler/investments",
    "oauthAgentBaseUrl": "https://api.authsamples-dev.com/tokenhandler/oauth-agent"
}

Step 11: Understand Web Security Headers

The web host now writes a number of security headers, the most interesting of which is the Content Security Policy. This has the following values, since the SPA now only makes remote calls via its API domain:

content-security-policy:
  default-src 'none';
  script-src 'self';
  connect-src 'self' https://api.authsamples-dev.com;
  child-src 'self';
  img-src 'self';
  style-src 'self';
  object-src 'none'
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self'
strict-transport-security: max-age=63072000; includeSubdomains; preload
x-frame-options: DENY
x-xss-protection: 1; mode=block 
x-content-type-options: nosniff
referrer-policy: same-origin

Local API Setup

It is also possible to run the Sample API that provides the SPA’s data on the local computer, but you then need to manage cookies for this routing. One way to do so is to run a local token handler. To do so, first ensure that a docker engine is installed, and also the envsubst tool.

Step A: Run the API

Select one of this blog’s final APIs from the below list, and follow its instructions, to run the API on port 446:

Step B: Update DNS

Next, add the local API subdomain to your computer’s hosts file:

127.0.0.1  localhost web.authsamples-dev.com apilocal.authsamples-dev.com
::1 localhost

Step C: Run the SPA against a Local API

To make the SPA connect to one of this blog’s final APIs, first ensure that the API is running. Then use a ‘LOCALAPI‘ command line argument when running the scripts described earlier:

./build.sh LOCALAPI
./run.sh LOCALAPI

This will run the utility token handler components in a small Docker Compose network. The SPA’s configuration will then be updated as follows, to route to the API via the local token handler rather than the cloud one:

{
    "apiBaseUrl": "https://apilocal.authsamples-dev.com:444/demobrand/investments",
    "oauthAgentBaseUrl": "https://apilocal.authsamples-dev.com:444/demobrand/oauth-agent"
}

Step D: Use the SPA and API

When you now use the SPA it will call the local API rather than a cloud API. The API behaviour includes logging output that is explained in later blog posts, under the API theme.

Step E: Understand Token Handler Deployment

To understand how I deploy the OAuth agent and OAuth proxy components, you can study my deployment resources. I use the Kong API Gateway and the following Docker Compose deployment settings:

version: '3.8'
services:

  apigateway:
    image: custom_kong:latest
    hostname: apigateway-internal.authsamples-dev.com
    extra_hosts:
     - apilocal.authsamples-dev.com:host-gateway
    ports:
      - 444:8000
    volumes:
      - ../environments/docker-local/gateway-routes.yml:/usr/local/kong/declarative/kong.yml
      - ../../certs/authsamples-dev.ssl.pem:/usr/local/share/certs/authsamples-dev.ssl.pem
      - ../../certs/authsamples-dev.ssl.key:/usr/local/share/certs/authsamples-dev.ssl.key
      - ../../certs/authsamples-dev.ca.pem:/usr/local/share/certs/authsamples-dev.ca.pem
    environment:
      KONG_DATABASE: 'off'
      KONG_DECLARATIVE_CONFIG: '/usr/local/kong/declarative/kong.yml'
      KONG_PROXY_LISTEN: '0.0.0.0:8000 ssl'
      KONG_SSL_CERT: '/usr/local/share/certs/authsamples-dev.ssl.pem'
      KONG_SSL_CERT_KEY: './usr/local/share/certs/authsamples-dev.ssl.key'
      KONG_LUA_SSL_TRUSTED_CERTIFICATE: './usr/local/share/certs/authsamples-dev.ca.pem'
      KONG_LOG_LEVEL: 'info'
      KONG_PLUGINS: 'bundled,oauth-proxy'
      KONG_NGINX_PROXY_PROXY_BUFFERS: '16 64k'
      KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: '64k'
      KONG_NGINX_PROXY_LARGE_CLIENT_HEADER_BUFFERS: '16 64k'

  oauthagent:
    image: oauthagent:latest
    hostname: oauthagent-internal.authsamples-dev.com
    volumes:
      - ../../certs/authsamples-dev.ssl.p12:/usr/oauth-agent/certs/authsamples-dev.ssl.p12
    env_file:
      - ../environments/docker-local/.env

The OAuth agent uses environment variables such as the following, to interact with the authorization server and for its cookie issuing:

PORT=8000
TRUSTED_WEB_ORIGIN='https://web.authsamples-dev.com'
ISSUER='https://cognito-idp.eu-west-2.amazonaws.com/eu-west-2_CuhLeqiE9'
AUTHORIZE_ENDPOINT='https://login.authsamples.com/oauth2/authorize'
TOKEN_ENDPOINT='https://login.authsamples.com/oauth2/token'
USERINFO_ENDPOINT='https://login.authsamples.com/oauth2/userInfo'
LOGOUT_ENDPOINT='https://login.authsamples.com/logout'
CLIENT_ID='7q5pope8rki7okarj2u8l4in7o'
CLIENT_SECRET='1d18g4v05sesjkv161borl012j009l7ooktnfs10ph9p6nkbbfl9'
REDIRECT_URI='https://web.authsamples-dev.com/spa/'
POST_LOGOUT_REDIRECT_URI='https://web.authsamples-dev.com/spa/loggedout'
SCOPE='openid profile https://api.authsamples.com/investments'
COOKIE_DOMAIN='apilocal.authsamples-dev.com'
COOKIE_NAME_PREFIX='mycompany'
COOKIE_ENCRYPTION_KEY='33be02f1b76feccf2c30a4847b0ad68d01756d7a9fb7f9a533b12b5d249a9c66'
CORS_ENABLED='true'
SERVER_CERT_P12_PATH='./certs/authsamples-dev.ssl.p12'
SERVER_CERT_P12_PASSWORD='Password1'

When using the token handler pattern you remotely deploy these components. You do not need to develop them. The frontend development setup is therefore focused solely on the user interface, in the same way as this blog’s earlier SPAs.

Step F: Free Docker Resources

To free resources in the Docker compose network, run this command:

./teardown.sh LOCALAPI

Where Are We?

We have explained how to run the final web sample, which has more moving parts than earlier code samples. The React demo SPA can be run as a single component under development. The app is in control of its own OpenID Connect flow. After user logins, the SPA calls deployed API components using secure cookies.

Next Steps