@genesislcap/foundation-auth
TypeScript icon, indicating that this package has built-in type declarations

14.173.2 • Public • Published

Foundation Auth

lerna TypeScript

foundation-auth is a fully featured authentication micro frontend that is http and cookies based. It allows your application to provide a more efficient and secure authentication experience, and enables functionality like popout windows. The package differs from foundation-login which authenticated over websockets and is now considered deprecated.

foundation-auth provides several exports to promote reuse and extensibility at various levels. These include but are not limited to:

  • ZeroAuth: A preconfigured version of the micro frontend built with the zero design system and zero components.
  • configure: A customisation hook for the base micro frontend that integrates it with your design system of choice.
  • AuthStore: An auth based foundation-store.
  • AuthMachine: An auth based foundation-state-machine covering the various auth workflows.
  • AuthMessageMapper: The auth message dto to entity mapper.
  • AuthRouting: A routing utility, which you can call navigateTo(...) to navigate to internal routes.
  • Various UI components / route screens, some of which are lazy loaded on-demand to optimise the experience.

For applications that do not or cannot use the DI system, we export utility functions to get each from the DI container. For example, getAuthStore, getAuthMachine, getAuthRouting etc.

Many of these are available as subpath exports and should be imported from these to optimise bundling and overall efficiency.

import { configure } from '@genesislcap/foundation-auth/configure';
import { AuthRouting } from '@genesislcap/foundation-auth/routing';
// note zero is on the root export
import { ZeroAuth } from '@genesislcap/foundation-auth';

In most cases, developers simply import the ZeroAuth micro frontend, or use the configure export token to tailor the micro frontend to their specific needs in their router config. However, developers can also use the exports provided to build their own authentication frontends or workflows. A set of pre-defined custom events are used to interact with the AuthStore and AuthMachine, and developers can provide custom implementations of parts of the machine's workflow.

Basic setup instructions

These examples are based on a host application using FAST and the FASTRouter. However, setup in the frontend and router of your choice should be quite similar.

Environment variables

foundation-auth uses the following environment variables. The .env file below shows the built-in defaults used with API_HOST.

# There should be nothing sensitive here!

# HTTP
GENX_LOGIN_URL=/sm/event-login-auth
GENX_LOGIN_REFRESH_URL=/sm/event-login-auth
GENX_LOGIN_DETAILS_URL=/sm/event-login-details
GENX_LOGOUT_URL=/sm/event-logout
GENX_CHANGE_PASSWORD_URL=/sm/event-change-user-password
GENX_FORGOT_PASSWORD_URL=/sm/event-self-service-password-reset
GENX_RESET_PASSWORD_URL=/sm/event-password-reset-action

# SSO (type and id will be replaced on runtime idp selection)
GENX_SSO_LIST_URL=/sm/sso/list
GENX_SSO_LOGIN_URL=/sm/{type}/login?idp={id}

If you are happy with these defaults then you have nothing more to do.

Here is an example of loading environment variables contained in a .env file into a webpack build, but how you set environment variables at an app level is really up to you.

const { resolveDefineConfig } = require('@genesislcap/build-kit'); // < npm install @genesislcap/build-kit --save
const { config } = require('dotenv'); // < npm install dotenv --save
const { DefinePlugin } = require('webpack');

config(); // < loads the .env vars

module.exports = {
  ...
  plugins: [
    new DefinePlugin(resolveDefineConfig(['GENX_*'])), // < code replacement should include 'API_HOST' if set, ie. ['GENX_*', 'API_HOST', ...]
  ],
}

Set up a route to host the micro frontend

Here we are lazy loading the micro frontend when the route is accessed.

{
  title: 'Authenticate',
  name: 'auth',
  path: 'auth', // < at what path should the micro frontend be accessed. Could be an empty string, ie. on the website root.
  element: async () => {
    const { configure } = await import('@genesislcap/foundation-auth/config');
    return configure({
      omitRoutes: ['request-account'],
      hostPath: 'auth', // < important to match the route path
      logo: myLogo,
      background: myBG,
      postLoginRedirect: () => {
        // You could inspect the user here and route them based on various conditions.
        Route.path.push('my-dashboard');
      },
    });
  },
  childRouters: true,
  settings: { public: true },
  layout: authLayout,
}

Checking the user authentication status during routing

Here in our FASTRouter's NavigationContributor, we check the user status as part of the routing flow.

import { User } from '@genesislcap/foundation-user';
...
@User private user: User;
...
this.contributors.push({
  navigate: async (phase) => {
    const settings = phase.route.settings;
    /**
     * Don't block public routes or any routes when authenticated
     */
    if (settings?.public || this.user.isAuthenticated) {
      return;
    }
    /**
     * Otherwise route them to auth
     */
    phase.cancel(() => {
      this.user.trackPath(); // < Track the user's path to return to it post login if required
      Route.name.replace(phase.router, 'auth');
    });
  },
});

Establishing a Websocket Connection

Creating an actual websocket connection to the Genesis backend is beyond the scope of foundation-auth. Post login you can import the API_HOST from @genesislcap/foundation-utils and connect to the Genesis backend. Below uses connect from the DI container.

import { API_HOST } from '@genesislcap/foundation-utils';
...
@Connect private connect: Connect,
...
this.connect.connect(API_HOST);

Logging out

You can logout easily by navigating to the logout route. To help, you can access the AuthRouting singleton via the DI container from anywhere in your app, such as a header's logout button, and call navigateTo.

import { AuthRouting } from '@genesislcap/foundation-auth/routing';
...
@AuthRouting private authRouting: AuthRouting;
...
this.authRouting.navigateTo('logout');

...or via a utility if your app is not using decorators or the DI container.

import { getAuthRouting } from '@genesislcap/foundation-auth/routing';
...
private authRouting = getAuthRouting();
...
this.authRouting.navigateTo('logout');

You can use AuthRouting to navigate to other routes, like change password etc., without needing to know the full path the micro frontend is hosted on.

If you have trouble logging out using the routing utility, you can try using your host app's router directly.

The following example is Angular based, where the developer has put the micro frontend on the auth path. There's logic within the micro frontend that will automatically navigate itself to the logout route if the login screen is loaded while the user is already logged in. Logging out is as easy as moving back to that route.

import { Router } from '@angular/router';

export class AppComponent {
  constructor(private router: Router) {}
  /**
   * Note the developer has put the micro frontend of the `auth` path.
   */
  onLogout() {
    /**
     * Navigate back to the micro frontend and it will take care of the logout.
     */
    this.router.navigateByUrl('auth');
    /**
     * Alternatively, you can navigate to the internal logout route.
     * this.router.navigateByUrl('auth/logout');
     */
  }
}

See the AuthRouting API Docs for more information.

Troubleshooting

  • We're using foundation-login, do we have to move to foundation-auth?
    • foundation-login authenticated over websockets and is now considered deprecated, but it will still work for the time being. Moving is advised and should be pretty seamless.
  • We're using configure but are not seeing our changes reflected?
    • Ensure you're importing configure from the /config subpath and not the root of the package.
    • Ensure you're not importing anything from the root of the package elsewhere in your application.
  • The Forgot Password?, Change Password and Request Account links don't seem to do anything.
    • If you're hosting the micro frontend on anything other than the top level root path '', for example: path: 'auth', then ensure the hostPath property in the configure matches.

Installation

To enable this module in your application, follow the steps below.

  1. Add @genesislcap/foundation-auth as a dependency in your package.json file. Whenever you change the dependencies of your project, ensure you run the $ npm run bootstrap command again. You can find more information in the package.json basics page.
{
  ...
  "dependencies": {
    ...
    "@genesislcap/foundation-auth": "latest"
    ...
  },
  ...
}

License

Note: this project provides front-end dependencies and uses licensed components listed in the next section; thus, licenses for those components are required during development. Contact Genesis Global for more details.

Licensed components

Genesis low-code platform

Readme

Keywords

none

Package Sidebar

Install

npm i @genesislcap/foundation-auth

Weekly Downloads

357

Version

14.173.2

License

SEE LICENSE IN license.txt

Unpacked Size

1.41 MB

Total Files

615

Last publish

Collaborators

  • genesisnpm