Skip to content

Instantly share code, notes, and snippets.

@timrijkse
Last active March 6, 2024 12:35
Show Gist options
  • Save timrijkse/e6a61ffb401f5399a39cc8d85bf4e5d1 to your computer and use it in GitHub Desktop.
Save timrijkse/e6a61ffb401f5399a39cc8d85bf4e5d1 to your computer and use it in GitHub Desktop.
MSAL Auth Provider for React
import React, {
createContext,
useContext,
useLayoutEffect,
useState,
} from "react";
import {
InteractionRequiredAuthError,
PublicClientApplication,
} from "@azure/msal-browser";
import { MsalProvider } from "@azure/msal-react";
import { msalConfig } from "../config/authConfig";
const LOGIN_SCOPES = [`${msalConfig.auth.clientId}/.default`];
// Initialize MSAL client
const msalInstance = new PublicClientApplication(msalConfig);
type AuthContextType = {
signIn: () => Promise<void>;
signOut: () => void;
refreshToken: () => Promise<string | undefined>;
accessToken: string | undefined;
};
const AuthContext = createContext<AuthContextType>({} as AuthContextType);
const initializeMSAL = async () => {
await msalInstance.initialize();
};
export const AuthProvider = ({
children,
}: {
children: JSX.Element | JSX.Element[];
}) => {
const [accessToken, setAccessToken] = useState<string>();
useLayoutEffect(() => {
initializeMSAL().then((response) => {
msalInstance
.handleRedirectPromise()
.then((response) => {
if (response !== null) {
setAccessToken(response.accessToken);
} else {
const accounts = msalInstance.getAllAccounts();
if (accounts.length > 0) {
msalInstance.setActiveAccount(accounts[0]);
refreshToken();
} else {
signIn();
}
}
})
.catch((error) => {
console.error("Error processing redirect:", error);
});
});
}, []);
const signIn = async () => {
const loginRequest = { scopes: LOGIN_SCOPES };
try {
await msalInstance.loginRedirect(loginRequest);
} catch (error) {
console.error("Error signing in", error);
}
};
const signOut = () => {
msalInstance.logoutRedirect();
};
const refreshToken = async (): Promise<string | undefined> => {
await msalInstance.initialize();
const request = { scopes: LOGIN_SCOPES };
try {
const response = await msalInstance.acquireTokenSilent(request);
if (response && response.accessToken) {
setAccessToken(response.accessToken);
return response.accessToken;
}
} catch (error) {
console.error("Error refreshing token", error);
if (error instanceof InteractionRequiredAuthError) {
msalInstance.acquireTokenRedirect(request);
}
}
};
return (
<MsalProvider instance={msalInstance}>
<AuthContext.Provider
value={{ signIn, signOut, refreshToken, accessToken }}
>
{children}
</AuthContext.Provider>
</MsalProvider>
);
};
// Hook to use auth context
export const useAuth = () => useContext(AuthContext);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment