AzureAD / microsoft-authentication-library-for-js

Microsoft Authentication Library (MSAL) for JS
http://aka.ms/aadv2
MIT License
3.64k stars 2.65k forks source link

MsalProvider with single-spa and multiple applications #4263

Closed yoshegg closed 2 years ago

yoshegg commented 2 years ago

Core Library

MSAL.js v2 (@azure/msal-browser)

Core Library Version

2.19.0

Wrapper Library

MSAL React (@azure/msal-react)

Wrapper Library Version

1.1.1

Description

We are using React and single-spa to implement our multi-frontend application. We have a navigation bar and an index part; these are separated into two different applications. Parts of these applications should be shown (or not) depending on the authentication of the user.

The problem is that we can't figure out how to use the mandatory <MsalProvider> in a way that it wraps around our application. Right now we use <MsalProvider> twice, which we know is not recommended and leads to the problem that the instance state is not synchronized among our microfrontends: One application works as expected, whereas the other's instance's context is not updated correctly. Refreshing the page or navigating to it results in unexpected behaviour.

Is there a way to use msal-react with single-spa while using multiple applications?

The user in the aformentioned issue solved his problem by using the vanilla javascript library.

Another user had a similar problem that was also linked to using <MsalProvider> in an inappropriate way; This seems to be related to an entirely different problem though.

MSAL Configuration

auth: {
        clientId,
        authority: '<my-authority>',
        knownAuthorities: ['<my-known-authority>'],
        redirectUri: '/',
        postLogoutRedirectUri: '/',
        navigateToLoginRequestUrl: false,
    },
    cache: {
        cacheLocation: 'localStorage',
        storeAuthStateInCookie: false,
    },

Relevant Code Snippets

// microfrontend-layout.html
<single-spa-router>
    <div>
        <div id="header"></div>
        <div>
            <div id="index"></div>
        </div>
    </div>
</single-spa-router>

// create_application.ts
import { registerApplication, start } from 'single-spa';
import { constructApplications, constructRoutes, constructLayoutEngine } from 'single-spa-layout';

import microfrontendLayout from './microfrontend-layout.html';

import msalInstance from './authenticationInstance';

const routes = constructRoutes(microfrontendLayout);
const applications = constructApplications({
    routes,
    loadApp({ name }) {
        return System.import(name);
    },
});

registerApplication(
    'navbar',
    () => import('./navbar/index.app').then((module) => module.default),
    () => true,
    { msalInstance },
);

registerApplication(
    'index',
    () => import('./index/index.app').then((module) => module.default),
    (location) => location.pathname === '/index.html' || location.pathname === '/',
    { msalInstance },
);

const layoutEngine = constructLayoutEngine({ routes, applications, active: false });

applications.forEach(registerApplication);
layoutEngine.activate();
start();

// navbar/index.app.tsx (similar to index/index.app.tsx, therefore we use MsalProvider twice)
import * as React from 'react';
import ReactDOM from 'react-dom';
import { MsalProvider } from '@azure/msal-react';
import singleSpaReact from 'single-spa-react';
import Navbar from './Navbar';

export default singleSpaReact({
    React,
    ReactDOM,
    rootComponent: (props) => (
        <MsalProvider instance={props.msalInstance}>
            <Navbar instance={props.msalInstance} />
        </MsalProvider>
    ),
    domElementGetter: () => document.getElementById('header'),
});

Identity Provider

Azure B2C Basic Policy

Source

External (Customer)

exaucae commented 2 years ago

Have your Provider called in an Auth microfrontend with will set the user credential/token in the localStorage ( as you want ). Then have your other MFEs read those credentials from localStorage and behave accordingly. The Auth MFE would be your entrypoint MFE in root-config & always active. It needs to reroute to other MFE based on user authentification.

MFE: Microfrontend.

samuelkubai commented 2 years ago

@yoshegg does the suggestion above work as a solution for you.

As as a library we do not have any official solutions other than the solutions stated above and the aforementioned issue, we however have this noted and have added this to our backlog.

yoshegg commented 2 years ago

@exaucae @samuelkubai We will try that and post our results. Thank you for your time.

exaucae commented 2 years ago

@yoshegg , here is an additionnal doc for the issue: https://github.com/exaucae/single-spa-patterns/blob/master/AUTHENTICATION.md

ghost commented 2 years ago

@yoshegg This issue has been automatically marked as stale because it is marked as requiring author feedback but has not had any activity for 5 days. If your issue has been resolved please let us know by closing the issue. If your issue has not been resolved please leave a comment to keep this open. It will be closed automatically in 7 days if it remains stale.