我正在尝试使用MSAL (react)库设置azure和b2c的next.js。Msal提供了一个很好的组件<MsalAuthenticationTemplate />
来处理授权。
我做了一个最小的next.js页面。
import { InteractionType } from "@azure/msal-browser";
import { MsalAuthenticationTemplate } from "@azure/msal-react";
import { NextPage } from "next";
const ErrorComponent = ({ error }: any) => {
return <p>an Error occured: {error}</p>;
};
const LoadingComponent = () => {
return <p>Authentication in progress...</p>;
};
const CreateAdvert: NextPage = () => {
return (
<>
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
errorComponent={ErrorComponent}
loadingComponent={LoadingComponent}
>
<p>content</p>
</MsalAuthenticationTemplate>
</>
);
};
export default CreateAdvert;
如果我复制它更简单,我仍然得到相同的错误:
import { InteractionType } from "@azure/msal-browser";
import {
useIsAuthenticated,
} from "@azure/msal-react";
import { NextPage } from "next";
const CreateAdvert: NextPage = () => {
const isAuthenticated = useIsAuthenticated();
if (!isAuthenticated) return <p>not logged in!</p>;
return <p>logged in!</p>;
};
export default CreateAdvert;
在浏览器控制台中,我可以看到以下错误:
Warning: Text content did not match. Server: "Authentication in progress..." Client: "content"
Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.
Uncaught Error: Text content does not match server-rendered HTML
Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering
我想知道如何解决这个问题?
我认为这部分是最大的线索
Warning: Text content did not match. Server: "Authentication in progress..." Client: "content"
这是否意味着我不能使用SSR或SSG ?
但是在FAQ中有一个答案说你可以使用MSAL和ssr。
https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-react/FAQ.md does-azuremsal-react-support-server-side-rendering-ssr-or-static-site-generation
是的!但是,身份验证不能在服务器端完成,您应该避免在服务器端调用msal api。@azure/msal-react抽象了一些逻辑,但如果你正在构建自定义身份验证逻辑,请确保在浏览器中呈现时调用所有api。您可以查看我们的Next.js示例和Gatsby示例。
如果我检查github存储库中的next.js示例,它看起来与我的应用程序几乎相同。
https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/samples/msal-react-samples/nextjs-sample
剩下的代码。
// _app.tsx
const conf = new MSAL.PublicClientApplication({
auth: {
clientId: process.env.NEXT_PUBLIC_B2C_WEBAPP_APP_ID as string,
redirectUri:
process.env.NODE_ENV === "development"
? process.env.NEXT_PUBLIC_B2C_REDIRECT_URI
: process.env.NEXT_PUBLIC_B2C_REDIRECT_URI,
authority: `https://${process.env.NEXT_PUBLIC_B2C_TENANT_NAME}.b2clogin.com/${process.env.NEXT_PUBLIC_B2C_TENANT_NAME}.onmicrosoft.com/${process.env.NEXT_PUBLIC_B2C_SIGNIN_SIGNUP_POLICY}`,
knownAuthorities: [
`${process.env.NEXT_PUBLIC_B2C_TENANT_NAME}.b2clogin.com`,
],
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
system: {
loggerOptions: {
logLevel: 0,
loggerCallback: (level, message, containsPii) => {
if (containsPii) {
return;
}
switch (level) {
case MSAL.LogLevel.Error:
console.error(message);
return;
case MSAL.LogLevel.Info:
console.info(message);
return;
case MSAL.LogLevel.Verbose:
console.debug(message);
return;
case MSAL.LogLevel.Warning:
console.warn(message);
return;
}
},
},
},
});
function MyApp({ Component, pageProps }: AppProps) {
return (
<MsalProvider instance={MSALInstance}>
<Component {...pageProps} />
</MsalProvider>
);
}
export default MyApp;
- 无论在哪里使用React组件,您都可以尝试通过使用
{ ssr: false }
使用'next/dynamic'动态导入它来解决此问题。
const Home = dynamic(
() => import('../components/Home'),
{ ssr: false }
)
- 这将阻止组件被添加到服务器,并强制它只在客户端动态加载。