-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
Add New Authentication Providers.zh CN
LobeChat 使用 Auth.js v5 作为外部身份验证服务。Auth.js 是一个开源的身份验证库,它提供了一种简单的方式来实现身份验证和授权功能。本文档将介绍如何使用 Auth.js 来实现新的身份验证方式。
为了在 LobeChat 中添加新的身份验证提供者(例如添加 Okta),你需要完成以下步骤:
首先,你需要查阅 Auth.js 提供者列表 来了解是否你的提供者已经被支持。如果你的提供者已经被支持,你可以直接使用 Auth.js 提供的 SDK 来实现身份验证功能。
接下来我会以 Okta 为例来介绍如何添加新的身份验证提供者
打开 src/app/api/auth/next-auth.ts
文件,引入 next-auth/providers/okta
import { NextAuth } from 'next-auth';
import Auth0 from 'next-auth/providers/auth0';
import Okta from 'next-auth/providers/okta';
// 引入 Okta 提供者
新增预定义的服务端配置
// 导入服务器配置
const { OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, OKTA_ISSUER } = getServerConfig();
const nextAuth = NextAuth({
providers: [
// ... 其他提供者
Okta({
clientId: OKTA_CLIENT_ID,
clientSecret: OKTA_CLIENT_SECRET,
issuer: OKTA_ISSUER,
}),
],
});
打开 src/config/server/app.ts
文件,在 getAppConfig
函数中新增 Okta 相关的环境变量
export const getAppConfig = () => {
// ... 其他代码
return {
// ... 其他环境变量
OKTA_CLIENT_ID: process.env.OKTA_CLIENT_ID || '',
OKTA_CLIENT_SECRET: process.env.OKTA_CLIENT_SECRET || '',
OKTA_ISSUER: process.env.OKTA_ISSUER || '',
};
};
修改在 src/features/Conversation/Error/OAuthForm.tsx
及 src/app/settings/common/Common.tsx
中的 signIn
函数参数
默认为 auth0
,你可以将其修改为 okta
以切换到 Okta 提供者,或删除该参数以支持所有已添加的身份验证服务
该值为 Auth.js 提供者 的 id,你可以阅读相应的 next-auth/providers
模块源码以读取默认 ID
在部署时新增 Okta 相关的环境变量 OKTA_CLIENT_ID
、OKTA_CLIENT_SECRET
、OKTA_ISSUER
,并填入相应的值,即可使用
在前端页面中使用 useOAuthSession()
方法获取后端返回的用户信息 user
:
import { useOAuthSession } from '@/hooks/useOAuthSession';
const { user, isOAuthLoggedIn } = useOAuthSession();
默认的 user
类型为 User
,类型定义为:
interface User {
id?: string;
name?: string | null;
email?: string | null;
image?: string | null;
}
user.id
用于标识用户。当引入新身份 OAuth 提供者后,您需要在 src/app/api/auth/next-auth.ts
中处理 OAuth 回调所携带的信息。您需要从中选取用户的 id
。在此之前,我们需要了解 Auth.js
的数据处理顺序:
authorize --> jwt --> session
默认情况下,在 jwt --> session
过程中,Auth.js
会自动根据登陆类型将用户 id
赋值到 account.providerAccountId
中。 如果您需要选取其他值作为用户 id
,您需要实现以下处理逻辑。
callbacks: {
async jwt({ token, account, profile }) {
if (account) {
// 您可以从 `account` 或 `profile` 中选取其他值
token.userId = account.providerAccountId;
}
return token;
},
},
如果您想在 session
中携带更多关于 profile
及 account
的信息,根据上面提到的 Auth.js
数据处理顺序,那必须先将该信息复制到 token
上。
示例:把用户头像 URL:profile.picture
添加到session
中:
callbacks: {
async jwt({ token, profile, account }) {
if (profile && account) {
token.userId = account.providerAccountId;
+ token.avatar = profile.picture;
}
return token;
},
async session({ session, token }) {
if (session.user) {
session.user.id = token.userId ?? session.user.id;
+ session.user.avatar = token.avatar;
}
return session;
},
},
然后补充对新增参数的类型定义:
declare module '@auth/core/jwt' {
interface JWT {
// ...
avatar?: string;
}
}
declare module 'next-auth' {
interface User {
avatar?: string;
}
}
如果您配置了多个身份验证提供者,并且他们的 userId
映射各不相同,可以在 jwt
方法中的 account.provider
参数获取身份提供者的默认 id ,从而进入不同的处理逻辑。
callbacks: {
async jwt({ token, profile, account }) {
if (profile && account) {
if (account.provider === 'Authing')
token.userId = account.providerAccountId ?? token.sub;
else if (acount.provider === 'Okta')
token.userId = profile.sub ?? token.sub;
else
// other providers
}
return token;
},
}
This is the 🤯 / 🤖 Lobe Chat wiki. Wiki Home
- Architecture Design | 架构设计
- Code Style and Contribution Guidelines | 代码风格与贡献指南
- Complete Guide to LobeChat Feature Development | LobeChat 功能开发完全指南
- Conversation API Implementation Logic | 会话 API 实现逻辑
- Directory Structure | 目录架构
- Environment Setup Guide | 环境设置指南
- How to Develop a New Feature | 如何开发一个新功能:前端实现
- New Authentication Provider Guide | 新身份验证方式开发指南
- Resources and References | 资源与参考
- Technical Development Getting Started Guide | 技术开发上手指南
- Testing Guide | 测试指南