react-auth-proxy

0.7.0 • Public • Published

react-auth-proxy

Pipeline status

Dependencies License Package

A turnkey solution for using authentication sessions in React built-in dev proxy 🧪🛡️.

Philosophy

The package is intended to be lightweight and configurable to support most usual authentication flows.

From react official doc for custom dev proxy setup, developers need to create a setupProxy.js file, that exports a function registering middlewares on an express-like app.

The module registers middlewares to manage a testing 3rd party authentication flow:

  • redirection to a login page
  • storing user sessions
  • setting end-user session cookie
  • logout endpoint

Usage

Install

npm install react-auth-proxy

Create a setupProxy.js file with your business logic

As a developer, I want my webapp to authenticate to an API server via JWT in a bearer token.

setupProxy.js (in the same folder as index.js)

const reactAuthProxy = require('react-auth-proxy')
const jsonwebtoken = require('jsonwebtoken')

const config = {
  auth: {
    presetUser: { name: 'Carlo', role: 'account-manager' },
    encode: user => 'bearer ' + jsonwebtoken.sign(user, 'secret'),
  },
  proxy: {
    target: 'http://api-server:8080',
  },
}

module.exports = reactAuthProxy(config)

Then restart the react dev server.

Config fields

Param Type Default value Description
auth.autoLogin bool false When true, automatically login as the first presetUser
auth.encode function JSON.stringify takes a user as single param and encodes it into the header
auth.headerName string authorization Name of the header consumed by the backend
auth.loginPath string /.auth/login Path to get the login form HTML page
auth.logoutPath string /.auth/logout Path to trigger the current user's session deletion
auth.presetUser
object or array or objects
{"name": "test"} The user data to provide to the backend for security checks (RBAC)
auth.redirectParamName string redirect Name of the query param carrying the url where to browse back after the login
auth.serverPath string or array of strings /local-server Path to reach the server APIs
auth.successPath string /.auth/success Path to get redirected for user creation after a successful login
proxy object {} Config forwarded to the http-proxy-middleware module
proxy.callback function undefined Called on the app, after all the registrations, used for custom registrations
proxy.target string http://localhost:8080 Dev instance of the server hosting the APIs
sessionCookie.name string session Name of the cookie stored on clend-side, holding the session ID value
sessionCookie.maxAge int 1000 * 60 * 60 * 24 * 7 = 1 week Number of milliseconds the cookie remains valid

Module exports and exposed functions

Default export: the proxy registerer constructor. Named export: the sessions storage object.

Exposed data:

  • the registerer merge of user config and default fields: config
  • the registerer core proxy middleware: tradeSessionForJwt
  • the registerer user extractor from the sessions, using the right cookie name: getUser.

Example

As a developer, I want my webapp to authenticate to an Azure App Service backend relying on Azure Active Directory.

The client only has access to a session ID stored in a cookie and an API Gateway trades it for a custom token on backend side.

setupProxy.js

const reactAuthProxy = require('react-auth-proxy')

const makeClaim = (typ, val) => ({typ, val})
function encodeMsUser(user) {
  const payload = {
    claims: [
      makeClaim('name', user.name),
      makeClaim('roles', user.role),
    ]
  }
  return Buffer.from(JSON.stringify(payload)).toString('base64')
}

const config = {
  auth: {
    presetUser: { name: 'Carlo', role: 'account-manager' },
    headerName: 'x-ms-client-principal',
    encode: encodeMsUser,
    serverPath: '/api-server/v1',
  },
  proxy: {
    target: 'http://api-server:8080',
  },
  sessionCookie: {
    name: 'aad-session-id',
    maxAge: 60000, // 1 minute
  },
}

module.exports = reactAuthProxy(config)

Get your React webapp redirected to a login page when the session has expired

Many of webapp developers rely on axios for API calls. Axios transparently follows the redirections during its calls, including the redirection to the login page that comes when the user session has expired.

To detect the login redirection, rely on the response content-type:

import axios from 'axios'

export const instance = axios.create({
  withCredentials: true,
  baseURL: 'api-server/v1',
  headers: {
    'content-type': 'application/json',
  },
})

const allowedRedirectDomains = [window.location.origin, "https://login.windows.net"]

instance.interceptors.response.use(
  resp => {
    const contentType = resp.headers['content-type']

    if(contentType.includes('text/html')
		&& allowedRedirectDomains.some(orig => resp.request.responseURL.startsWith(orig))) {
      console.log('Refresh for new credendials', resp.request.responseURL)
      const loginParams = new URLSearchParams()
      loginParams.set("redirect", window.location)

      const respUrl = new URL(resp.request.responseURL)
      respUrl.search = "?" + loginParams // Override any API ref
      window.location = respUrl
      return
    }
    return resp.data
  },
  error => {
    throw error
  }
)

Any API call witnessing an expired session will result in the whole webapp browsing to the login page and provide a redirect parameter to come back at the end of the authentication.

# Redirection after a logout The client can set a query param called post_logout_redirect_uri (same as Azure) when calling the logout so the proxy will redirect it to the given URL once the logout is done.

Flow sequence

sequenceDiagram
	participant b as Browser
	participant r as React Web App
	participant p as React Auth Proxy
	participant s as API server

	autonumber

  Note over b, s: No session yet

  b->>r: Browse a webapp page

	Note over r: No session cookie
	r->>p: Initial API request<br/>for the API server

	p->>p: Read the session cookie<br/>and check for user session

	Note over p: No session found<br/>trigger a login

	p->>r: Login HTML page

	r->>b: Change the window.location<br/>to the login page
	Note over b: Browse the login page
	b->>p: The user selects the test user

	p->>b: Change the window.location<br/>to the success URL
	b->>p: Get on the success URL
	Note over p: New session created
  p->>b: Set the session cookie<br/>and redirect to the original webapp page

  Note over b, s: Existing session

  b->>r: Browse the original webapp page

	Note over r: With a session cookie
	r->>p: New API request<br/>for the API server

	p->>p: Read the session cookie<br/>and check for user session

	Note over p: A session found<br/>proxy to the API server

	p->>s: API request<br/>+ encoded user data (JWT, ...)
  Note over s: Read user data (RBAC, ...)
	s->>r: API response

Package Sidebar

Install

npm i react-auth-proxy

Weekly Downloads

169

Version

0.7.0

License

ISC

Unpacked Size

14.6 kB

Total Files

4

Last publish

Collaborators

  • ggmath