Next.js 15+NextAuth中Github/Google登录图标不显示求助
问题背景
使用Next.js 15 + NextAuth实现登录功能,因业务依赖SharedArrayBuffers,需配置以下响应头:
Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Opener-Policy: same-origin
配置后,登录页面的Github、Google等第三方登录图标无法加载,控制台报错:
The resource at “https://authjs.dev/img/providers/github.svg” was blocked due to its Cross-Origin-Resource-Policy header (or lack thereof)
问题原因
开启require-corp后,浏览器会拦截所有未明确允许跨域嵌入的外部资源。authjs.dev提供的默认登录图标未配置符合要求的Cross-Origin-Resource-Policy头,因此被拦截。
解决方案
替换NextAuth的默认外部图标为本地资源,步骤如下:
1. 下载并存放图标
将Github、Google等提供商的图标下载到项目的public/providers目录下(需自行创建该目录)。
2. 自定义登录组件,使用本地图标
修改app/components/auth_components.tsx,添加图标元素并引用本地资源:
import { signIn } from "@/auth"; import { Button } from "./ui/button"; export function SignIn({ provider, ...props }: { provider?: string } & React.ComponentPropsWithRef<typeof Button>) { // 根据provider选择对应本地图标 const getProviderIcon = () => { switch (provider) { case "github": return "/providers/github.svg"; case "google": return "/providers/google.svg"; default: return ""; } }; return ( <form action={async () => { "use server"; await signIn(provider, { redirectTo: "/dashboard" }); }} > <Button {...props}> {provider && ( <img src={getProviderIcon()} alt={`${provider} logo`} className="mr-2 h-4 w-4" /> )} Sign In with {provider?.charAt(0).toUpperCase() + provider?.slice(1)} </Button> </form> ); }
3. 更新导航栏组件的调用
修改app/ui/navbar.tsx,明确指定provider参数:
import { auth } from "@/auth"; import { SignIn } from "@/components/auth_components"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import Link from "next/link"; export default async function Navbar() { const session = await auth(); return ( <div className="flex items-center gap-4"> {session?.user ? ( <Avatar> {session.user.image !== null ? ( <AvatarImage src={session.user.image} crossOrigin="anonymous" /> ) : ( <AvatarImage src="default_avatar.svg" /> )} <AvatarFallback>{session.user.name?.charAt(0)}</AvatarFallback> </Avatar> ) : ( <div className="flex gap-2"> <SignIn provider="github" variant="outline" /> <SignIn provider="google" variant="outline" /> </div> )} </div> ); }
4. 保留原有的COOP/CORP头配置
next.config.js的头配置无需修改,继续保持以支持SharedArrayBuffers:
import type { NextConfig } from "next"; const nextConfig: NextConfig = { // 其他配置项 }; module.exports = { ...nextConfig, async headers() { return [ { source: "/(.*)", headers: [ { key: "Cross-Origin-Embedder-Policy", value: "require-corp", }, { key: "Cross-Origin-Opener-Policy", value: "same-origin", }, ], }, { source: "/lib/(.*)", headers: [ { key: "Cross-Origin-Embedder-Policy", value: "require-corp", }, ], }, ]; }, }; export default nextConfig;
说明
通过使用本地图标,避免了跨域资源加载的CORP限制,同时保留了SharedArrayBuffers所需的COOP/CORP头配置。如果需要使用其他第三方资源,需确保资源提供者配置了允许你的域名访问的Cross-Origin-Resource-Policy头,或者通过Next.js的next/image组件进行代理(需配置remotePatterns)。
内容的提问来源于stack exchange,提问作者Rohan Garg

