我有一个 NextJS 应用程序,它使用 Auth0 进行身份验证。我有两个 Auth0 租户,我想将它们用于两个单独的注册和登录功能。我知道我可以在一个角色中创建角色并且只能使用一个角色,但这不是一种选择。我在 [...nextauth].ts 文件中添加了两个 Auth0 提供程序,如下所示。基本上,我想要的是有两个登录按钮,一个具有 Auth0 租户 1 的 Auth0 提供程序,另一个具有 Auth0 租户 2 的 Auth0 提供程序。我使用 next-auth/react 进行登录(“auth0”) ,并且我希望能够指定应使用哪个 Auth0 提供程序来处理此问题。这是我的代码:
[...nextauth].ts:
import NextAuth, { type NextAuthOptions } from 'next-auth'
import Auth0Provider from 'next-auth/providers/auth0'
export const authOptions: NextAuthOptions = {
// Configure one or more authentication providers
secret: process.env.AUTH0_SECRET,
pages: {
signIn: '/login'
},
providers: [
Auth0Provider({
clientId: process.env.AUTH0_CLIENT_ID as string,
clientSecret: process.env.AUTH0_CLIENT_SECRET as string,
idToken: true,
issuer: process.env.AUTH0_ISSUER_BASE_URL
}),
Auth0Provider({
clientId: process.env.AUTH0_TENANT_CLIENT_ID as string,
clientSecret: process.env.AUTH0_TENANT_CLIENT_SECRET as string,
idToken: true,
issuer: process.env.AUTH0_TENANT_ISSUER_BASE_URL
})
],
callbacks: {
signIn({ profile }) {
return !!profile
},
redirect({ url, baseUrl }) {
return url.startsWith(baseUrl) ? `${baseUrl}/` : baseUrl
},
jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token
}
return token
},
session({ session, token }) {
return { ...session, ...token }
}
}
}
export default NextAuth(authOptions)
这是我的登录按钮的代码:
// material-ui
import { Button, Grid, Typography } from '@mui/material'
// assets
import LockIcon from '@mui/icons-material/Lock'
// func
import { useLanguage } from '@/hooks/i18n/useLanguage'
import { signIn } from 'next-auth/react'
const LoginBtn = () => {
const { t } = useLanguage()
return (
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justifyContent="center"
className="h-screen">
<Button
className="h-20 w-72 rounded-full bg-arealizeGreenDark text-arealizeBeigeLight hover:bg-arealizeGreenLight"
onClick={() => {
void signIn('auth0')
}}>
<Typography>{t.general.login_btn}</Typography>
<LockIcon className="ml-2" />
</Button>
</Grid>
)
}
export default LoginBtn
如您所见,我在 [...nextauth].ts 文件中实现了两个 Auth0Provider。这样,当我单击登录按钮时,它总是选择顶级提供商。我想要一种方法来指定应使用哪个提供程序。
谢谢!
您必须为每个提供商指定一个唯一的
id
:
[
Auth0Provider({
id:"first", // <-- add this line
clientId: process.env.AUTH0_CLIENT_ID as string,
clientSecret: process.env.AUTH0_CLIENT_SECRET as string,
idToken: true,
issuer: process.env.AUTH0_ISSUER_BASE_URL,
}),
Auth0Provider({
id:"second", // <-- add this line
clientId: process.env.AUTH0_TENANT_CLIENT_ID as string,
clientSecret: process.env.AUTH0_TENANT_CLIENT_SECRET as string,
idToken: true,
issuer: process.env.AUTH0_TENANT_ISSUER_BASE_URL,
}),
];
然后使用您要登录的提供商的 ID 调用
signIn()
方法:
signIn('first')
//or
signIn('second')
所以,我面临着类似的问题,终于弄清楚了......我必须查看 next-auth 的文档来确定 Auth0Provider 实际返回的内容(https://github.com/nextauthjs/next-auth /blob/v4/packages/next-auth/src/providers/auth0.ts)
然后,查看下一个身份验证文档为我提供的自定义 OAUTH 设置,我获取了从 Auth0 提供商代码返回的字段,并提出了一个如下所示的提供商对象:
{
id: 'first',
name: 'Auth0',
wellKnown: `${env.oauth.baseUrl}/.well-known/openid-configuration`,
type: 'oauth',
checks: ['pkce', 'state'],
idToken: true,
profile(profile) {
return {
id: profile.sub,
name: profile.nickname,
email: profile.email,
image: profile.picture,
};
},
clientId: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
issuer: process.env.OAUTH_URL,
token: {
params: {
// Add any other token endpoint params here
scope: 'openid email profile',
},
},
authorization: {
params: {
// Add any other authorization endpoint params here
scope: 'openid email profile',
connection: FOR MY SAKE I USED DIFFERENT DB CONNECTIONS,
},
},
}
最后,对于我提供的提供者数组:
providers = [{
id: 'first',
name: 'Auth0',
wellKnown: `${env.oauth.baseUrl}/.well-known/openid-configuration`,
type: 'oauth',
checks: ['pkce', 'state'],
idToken: true,
profile(profile) {
return {
id: profile.sub,
name: profile.nickname,
email: profile.email,
image: profile.picture,
};
},
clientId: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
issuer: process.env.OAUTH_URL,
token: {
params: {
// Add any other token endpoint params here
scope: 'openid email profile',
},
},
authorization: {
params: {
// Add any other authorization endpoint params here
scope: 'openid email profile',
connection: FOR MY SAKE I USED DIFFERENT DB CONNECTIONS,
},
},
},
{
id: 'second',
name: 'Auth0',
wellKnown: `${env.oauth.baseUrl}/.well-known/openid-configuration`,
type: 'oauth',
checks: ['pkce', 'state'],
idToken: true,
profile(profile) {
return {
id: profile.sub,
name: profile.nickname,
email: profile.email,
image: profile.picture,
};
},
clientId: process.env.AUTH0_OTHER_CLIENT_ID,
clientSecret: process.env.AUTH0_OTHER_CLIENT_SECRET,
issuer: process.env.OAUTH_URL,
token: {
params: {
// Add any other token endpoint params here
scope: 'openid email profile',
},
},
authorization: {
params: {
// Add any other authorization endpoint params here
scope: 'openid email profile',
connection: FOR MY SAKE I USED DIFFERENT DB CONNECTIONS,
},
},
},
],
然后,由于很多配置都是相同的,所以我重构了一个函数,该函数采用我需要更改的字段的参数并返回所需的配置对象。
希望这有帮助!黑客快乐!