This library contains some common patterns including:
-
Private Components which are only displayed to users who are logged in
-
Protected Components which are only displayed to users who have been assigned the correct roles (RBAC)
-
Force Login Once so that users are automatically prompted to login when a page / component is displayed for the first time and aren't already logged in.
-
Connect MSAL-Browser with MGT Components so that you can take advantage of the awesome Microsoft Graph Toolkit for React Components, and use msal-browser to manage your own components.
I like to start by instantiating an MSAL Public Client Application in a msal-config.ts
file, like so:
// auth-config.ts
import { Configuration, PublicClientApplication } from "@azure/msal-browser";
import { Providers as MGT_Providers } from "@microsoft/mgt-element/dist/es6";
import { Msal2Provider as MGT_Msal2Provider } from "@microsoft/mgt-msal2-provider/dist/es6";
const configuration: Configuration = {
auth: {
// provide clientId and authority in the build environment or a .env file
clientId: process.env.REACT_APP_CLIENT_ID,
authority: process.env.REACT_APP_AUTHORITY,
redirectUri: window.location.origin,
},
};
export const MSAL_instance = new PublicClientApplication(configuration);
MGT_Providers.globalProvider = new MGT_Msal2Provider({
publicClientApplication: MSAL_instance,
});
and then wrap the application with the MsalProvider
in the usual way:
// index.tsx
import { App } from './/app';
import { MSAL_instance } from "./auth/configuration"
import { MsalProvider } from "@azure/msal-react";
ReactDOM.render(
<MsalProvider instance={MSAL_instance}>
<App />
</MsalProvider>,
document.getElementById('root')
);
Connecting the MSAL provider with Microsoft Graph Tookit for React is as easy as:
// app.tsx
import { useConnectMGT } from 'react-msal-helpers';
export const App = () => {
useConnectMGT()
... your application
};
Note that useConnectMGT()
must be called in a component wrapped in <MsalProvider>
.
To require that a user be logged in to view a component, use:
import { PrivateComponent } from 'react-msal-helpers';
<PrivateComponent
/* This component is rendered when the user is not logged in */
unauthenticated={UnauthenticatedComponent}
/* This component is rendered when the MSAL Provider status is "startup" */
loading={LoadingComponent}
/* The protected component */
content={ProtectedComponent}
/>
To require that a user be logged in and have the appropriate Application Registration Permissions (RBAC), use:
import { RBACProtectedComponent } from 'react-msal-helpers';
<RBACProtectedComponent
/* This component is rendered when if the user is logged
in but does not have the correct App Registration Roles */
unauthorized={UnauthorizedComponent}
/* This component is rendered when the user is not logged in */
unauthenticated={UnauthenticatedComponent}
/* This component is rendered when the MSAL Provider status is "startup" */
loading={LoadingComponent}
/* The protected componenet is visible if the user has been granted **This** role */
requiredRole="some_role"
/* The protected componenet is visible if the user has been granted **All of** these roles */
requiredRoles={["some_role","some_other_role"]}
/* The protected componenet is visible if the user has been granted **Any of** these roles */
allowedRoles={["some_role","some_other_role"]}
/* The protected component */
content={ProtectedComponent}
/>
Private and Protected routing is accomplished by passing the appropriate redirect component for your favorite React Routing library. For example, this can be accomplished with react-router-dom using:
import { PrivateComponent, RBACProtectedComponent } from 'react-msal-helpers';
import { Switch, Route, Redirect } from 'react-router-dom';
const MyPrivateRoute = props => (
<PrivateComponent
loading={"loading accounts data..."}
unauthenticated={() => <Redirect to="/pleaseLogIn" />}
content={() => <p>Private Content</p>}
/>
)
const MyProtectedRoute = props => (
<RBACProtectedComponent
requiredRole="something"
loading={"loading accounts data..."}
unauthorized={() => <Redirect to="/unauthorized" />}
unauthenticated={() => <Redirect to="/pleaseLogIn" />}
content={() => <p>Protected Content</p>}
/>
)
const MyAppRouter= props => (
<Switch>
<Route exact path='/private' render={MyPrivateRoute} />
<Route exact path='/protected' render={MyProtectedRoute} />
<Route exact path='/unauthorized' render="UNAUTHORIZED" />
<Route exact path='/pleaseLogIn' render={() => <p>Please log in</p>} />
</Switch>
)
If logging in is required to view an application or component, you can save the user a click and a few moments by automatically starting the login process. This can be accomplished using a hook like so:
import { useForceLoginOnce } from 'react-msal-helpers';
const App = props => {
useForceLoginOnce()
...
}
or with a compnent wrapper like so:
import { ForceAuthenticationOnce } from 'react-msal-helpers';
<ForceAuthenticationOnce
/* This component is rendered when the login is being initialized automatically */
forcingLoginMessage={() => <p>Logging you in</p>}
/* Content to render when the user is not logged in and authentication is not being forced */
unauthenticated={() => <p>Please log in</p>}
/* Rendered when the MsalAppliation state is "startup" */
loading={() => <p>Loading account data</p>}
/* The content to render */
content={App}
/>
Note that useForceLoginOnce()
and <ForceAuthenticationOnce/>
must be used
in a component wrapped in <MsalProvider>
.
- MSAL supports multiple simultaneous accounts These pickers use the "active account" for auth/auth.