question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

NextJS SSR support for navigateToLoginRequestUrl

See original GitHub issue

Core 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:

  1. Clone and check out this tag in my sample repository
  2. Install dependencies
  3. Duplicate env.sample to env.local and add your B2C instance and Auth Code + PKCE policy name.
  4. Run the sample
  5. Navigate to “My Details” (/me)
  6. 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:closed
  • Created a year ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
sameeragcommented, Jul 24, 2022

Thanks @jeroenheijmans. Sorry that we could not help your use case. @EmLauber marking this as won't fix. If we ever plan to support Next JS we can re-open this as needed.

2reactions
sameeragcommented, Jul 12, 2022

Yes, we unfortunately do not support complete SSR today with msal-browser. Will msal-node help in your case and can you hydrate your client session with SSO?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Next.Js SSR support example · Issue #5038 - GitHub
I would like to request to include an example which shows how to use MSAL on Server side rendering with Next.Js.
Read more >
1 - Stack Overflow
Wherever the React component is used, you may try to resolve this issue by dynamically importing it with 'next/dynamic' using { ssr: false...
Read more >
Basic Features: Pages - Next.js
This new directory has support for layouts, nested routes, and uses Server Components by default. ... Also referred to as "SSR" or "Dynamic...
Read more >
Client-Side and Server-Side Redirects in Next.js
Tagged with nextjs, redirect, ssr, react. ... Next.js supports both client-side and server-side rendering (SSR) and unfortunately the method ...
Read more >
Adding SSR functionality to a static Next.js app
Use the AWS Command Line Interface to change the app's platform type. Add a service role to the app. Update the output directory...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found