最近在做前后端分离,常见的有两种方案,一个是 bundle 打包成 js 文件,再嵌入 web 的某个页面;另外一个前端单独起一个服务器,用前端来负责页面和 SSO 相关的功能,后端只管提供 API 数据。这次用的是第二种方式,因为我想把后端作为纯的 API 服务器。
NextAuth
安装 NextAuth 包 yarn add next-auth
引入 SessionProvider
"use client";
import { SessionProvider } from "next-auth/react";
export default function RootLayout({
children,
}: {
children: React.ReactNode,
}) {
return (
<html lang="en">
<body>
<SessionProvider>{children}</SessionProvider>
</body>
</html>
);
}
在 Azure 上注册 application
按照微软的文档,注册一个 application,获取到client_id
和client_secret
。
留意设置好 callback URL 如下。
配置环境变量
创建.env.local
文件,配置好环境变量
AZURE_AD_CLIENT_ID=xxx-xxx-xxxx
AZURE_AD_CLIENT_SECRET=xxx-xxx-xxxx
AZURE_AD_TENANT_ID=xxx-xxx-xxxx
NEXTAUTH_SECRET=xxx-xxx-xxxx
NEXTAUTH_URL=http://localhost:3000
创建 route.ts
// app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import AzureADProvider from "next-auth/providers/azure-ad";
const handler = NextAuth({
session: {
strategy: "jwt",
},
providers: [
AzureADProvider({
clientId: process.env.AZURE_AD_CLIENT_ID!,
clientSecret: process.env.AZURE_AD_CLIENT_SECRET!,
tenantId: process.env.AZURE_AD_TENANT_ID,
}),
],
callbacks: {
jwt: async ({ token, account }) => {
console.log("jwt");
console.log("account", account);
console.log("token", token);
return token;
},
session: async ({ session, token }) => {
console.log("session");
console.log("session", session);
console.log("token", token);
return session;
},
},
});
export { handler as GET, handler as POST };
更新主页
因为用了useSession
,需要先判断 session 获取完成了,在判断是否登陆。如果是 loading,就先给一个空页面,直到获取到 session。
"use client";
import Home from "../components/Home";
import { useSession, signIn } from "next-auth/react";
const Page = () => {
const { data: session, status: status } = useSession();
console.log("browser session", session);
console.log("browser status", status);
if (status === "loading") {
return <div />;
} else if (session) {
return <Home />;
} else {
signIn();
}
};
export default Page;