4

I am working on a React App and am using the @azure/msal-react library for authentication.

This is working great , but then I realized I'd quite like to use the people picker widget from the @microsoft/mgt-react library.

Is there any way I can wire up my existing @azure/msal-react / @azure/msal-browser libraries to the MGT library?

Or do I have to refactor my code to use the MGT style auth methods?

If that's the case I'll just build my own People Picker component I think, but I thought I'd see if it was possible anyway.

John McAulay
  • 185
  • 9
  • Hmm I've done some more reading and it looks like I need to set up a "Custom Provider", am I on the right track? https://learn.microsoft.com/en-us/graph/toolkit/providers/custom – John McAulay Jun 18 '21 at 04:51

2 Answers2

4

My solution is to use the same @azure/msal-browser instance in both the Microsoft Graph Toolkit (@microsoft/mgt-element) and @azure/msal-react libraries, like so:

// MSAL React
import { MsalProvider as MsalReactProvider } from "@azure/msal-react";
import { Configuration, PublicClientApplication } from "@azure/msal-browser";
// Microsoft Graph Toolkit
import { Providers as MGT_Providers } from '@microsoft/mgt-element';
import { Msal2Provider as MGT_Msal2Provider } from '@microsoft/mgt-msal2-provider';

// Your app
import App from './App';

// MSAL configuration
const configuration: Configuration = {
    ... MSAL Browser config
};

// Instantiate MSAL-Browser
const pca = new PublicClientApplication(configuration);
// instantiate the global provider for MGT
MGT_Providers.globalProvider = new MGT_Msal2Provider({ publicClientApplication: pca });

ReactDOM.render(
  <MsalReactProvider instance={pca}>
    <App />
  </MsalReactProvider>  document.getElementById('root')
);

And then do a little bootstrapping in the app component to keep the login states in sync:

import { useMsal, useIsAuthenticated } from "@azure/msal-react";
import { Providers as MGT_Providers, ProviderState } from '@microsoft/mgt-element';

export function App() {

  const isAuthenticated = useIsAuthenticated();
  const { inProgress } = useMsal();
  useEffect(() => {
    console.log("isAuthenticated, inProgress: ", [isAuthenticated, inProgress], [typeof isAuthenticated, typeof inProgress])
    MGT_Providers.globalProvider.setState(inProgress !== "none" ? ProviderState.Loading : (isAuthenticated ? ProviderState.SignedIn : ProviderState.SignedOut))
  }, [isAuthenticated, inProgress])

  ... 

}
Jthorpe
  • 9,756
  • 2
  • 49
  • 64
3

If you already have a way to get an access token, you can use MGT with the SimpleProvider.

import {Providers, SimpleProvider, ProviderState} from '@microsoft/mgt-element';

Providers.globalProvider = new SimpleProvider((scopes: string[]) => {
  // return a promise with accessToken
});

// set state to signal to all components to start calling graph
Providers.globalProvider.setState(ProviderState.SignedIn)
Nikola Metulev
  • 566
  • 3
  • 7
  • Thanks so much, I found that in the documentation just before (see above comment). I'm struggling with i, but I'm sure I can figure it out tonight. If I have any more questions I'll post them here, but this is definitely the answer. Thanks so much. – John McAulay Jun 18 '21 at 04:58
  • Cheers bro, I got it sorted! Thanks so much for the speedy reply. – John McAulay Jun 18 '21 at 05:06