NextJS SSR support for navigateToLoginRequestUrl
See original GitHub issueCore Library
MSAL.js v2 (@azure/msal-browser)
Core Library Version
^2.26.0
Wrapper Library
MSAL React (@azure/msal-react)
Wrapper Library Version
^1.4.2
Description
When using the redirect flow in a NextJS application, I expect the server to already redirect to the correct route. In the current library this seems to happen client side. This prevents us from making full use of Server Side Rendering, and presents the user with a “flash” of the SPA’s root page.
MSAL Configuration
export const msalConfig = {
auth: {
clientId,
authority: `https://${tenant}.b2clogin.com/${tenant}.onmicrosoft.com/${b2cPolicy}`,
knownAuthorities: [`${tenant}.b2clogin.com`],
redirectUri: "/",
postLogoutRedirectUri: "/",
},
system: {
loggerOptions: {
loggerCallback(_level, message, _containsPii) {
if (!hideConsoleLogging) {
console.log(message);
}
},
},
},
};
export const loginRequest = {
scopes: ["openid", "profile", "email"],
};
Relevant Code Snippets
We use a CustomNavigationClient
per the NextJS sample from this repository:
import { NavigationClient } from "@azure/msal-browser";
// See: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-react/docs/performance.md#how-to-configure-azuremsal-react-to-use-your-routers-navigate-function-for-client-side-navigation
export class CustomNavigationClient extends NavigationClient {
constructor(router) {
super();
this.router = router;
}
async navigateInternal(url, options) {
console.log("Redirecting to page", url);
const relativePath = url.replace(window.location.origin, "");
if (options.noHistory) { this.router.replace(relativePath); }
else { this.router.push(relativePath); }
return false;
}
}
And the expected outcome is to see the console.log
on the Node console for NextJS. After getting redirected back to our SPA from Azure B2C I expect the target route to be picked up before the browser gets to see anything.
We wrap the target page component (linked to with <Link href="/me">
) like so:
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
authenticationRequest={loginRequest}
errorComponent={ErrorComponent}
loadingComponent={LoadingOverlay}
>
{props.children}
</MsalAuthenticationTemplate>
I’ve added some router debugging to my _app.js
like so:
useEffect(() => {
const logger = (url) => console.log('===> routeChangeStart to', url);
router.events.on('routeChangeStart', logger);
return () => { router.events.off('routeChangeStart', logger); }
});
And it confirms the problem: the client lands at /
and gets a router change event to /me
from MSAL, after the user already sees /
.
A full reproducible scenario:
- Clone and check out this tag in my sample repository
- Install dependencies
- Duplicate
env.sample
toenv.local
and add your B2C instance and Auth Code + PKCE policy name. - Run the sample
- Navigate to “My Details” (
/me
) - Enter your sign in details at B2C, click login to get redirected back
Then:
- Result: you get sent to
/
and the SSR leaves you there, the client shows that page, and after a short bit redirects you client side to/me
- Expected: the
CustomNavigationClient
should run server side and send you to/me
before hitting the browser - Acceptable workaround: a (documented) way to delay rendering in the client until MSAL is sure that all redirect work has been done
Hope that’s enough details! I’ve asked a strongly related Stack Overflow question too, but no answers yet. Let me know if you need more details.
Identity Provider
Azure B2C Basic Policy
Source
External (Customer)
Issue Analytics
- State:
- Created a year ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
Thanks @jeroenheijmans. Sorry that we could not help your use case. @EmLauber marking this as
won't fix
. If we ever plan to supportNext JS
we can re-open this as needed.Yes, we unfortunately do not support complete SSR today with
msal-browser
. Willmsal-node
help in your case and can you hydrate yourclient
session with SSO?