-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
I was monitoring my network calls when using your solution with React Admin and Azure AD B2C authentication. With your solution the access token gets fetched on every single HTTP request, again and again. This is due to the MSAL instance not being the same as what you pass down with React components and via props.
I went through the @azure/msal-react library and came up with the following solution:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { PublicClientApplication, InteractionType } from '@azure/msal-browser';
import { MsalProvider, MsalAuthenticationTemplate } from '@azure/msal-react';
import { msalConfig } from './authConfig';
const msalInstance = new PublicClientApplication(msalConfig);
ReactDOM.render(
<React.StrictMode>
<MsalProvider instance={msalInstance}>
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
>
<App />
</MsalAuthenticationTemplate>
</MsalProvider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();// src/App.js
import * as React from 'react';
import { Admin, Resource } from 'react-admin';
import { CategoriesList } from './categories/CategoriesList';
import { ProductsList } from './products/ProductsList';
import LogoutButton from './LogoutButton';
import dataProvider from "./dataProvider";
import { useMsal, useAccount } from "@azure/msal-react";
const App = () => {
const { instance, accounts } = useMsal();
const account = useAccount(accounts[0] || {});
React.useEffect(() => {
if (account) {
instance.acquireTokenSilent({
scopes: ["openid", "offline_access"],
account: account
}).then((response) => {
if(response) {
// Always use this as the most recent access token
localStorage.setItem("access_token", response.idToken);
}
});
}
}, [account, instance]);
return (
<Admin logoutButton={LogoutButton} dataProvider={dataProvider}>
<Resource name="categories" list={CategoriesList} />
<Resource name="products" list={ProductsList} />
</Admin>
);
}Now as you use localStorage here, you always refresh the access token received from the MSAL instance, be it from cache or from a network call. You can then use it in yor httpClient.
const httpClient = async (url, options = {}) => {
const accessToken = localStorage.getItem('access_token');
if (accessToken) {
if (!options.headers) {
options.headers = new Headers({ Accept: 'application/json' });
}
options.headers.set('Authorization', `Bearer ${accessToken}`);
}
return fetchUtils.fetchJson(url, options);
};My authConfig.js looks like this (little different with B2C I think):
// Config object to be passed to Msal on creation
export const msalConfig = {
auth: {
clientId: process.env.REACT_APP_CLIENT_ID,
authority: `https://${process.env.REACT_APP_TENANT_NAME}.b2clogin.com/nicehomecashregisterapp.onmicrosoft.com/${process.env.REACT_APP_POLICY}`,
knownAuthorities: [`${process.env.REACT_APP_TENANT_NAME}.b2clogin.com`],
redirectUri: "http://localhost:3000/",
postLogoutRedirectUri: "http://localhost:3000/",
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "localStorage", // This configures where your cache will be stored
storeAuthStateInCookie: true, // Set this to "true" if you are having issues on IE11 or Edge
}
};Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels