要使用自定义认证提供者进行自托管,您需要执行以下步骤。
您可以通过扩展 AbstractAuthProvider 类并实现以下函数来实现。
authenticate: 当用户进入 /admin 且未登录时(由 getUser 确定)调用此函数。此函数应重定向用户到登录页面或执行任何必要的操作以认证用户。
getUser: 当用户进入 /admin 时调用此函数,用于确定用户是否已登录。如果返回一个真值,用户已登录。如果返回一个假值,用户未登录。
getToken: 当请求发送到 GraphQL 端点时调用此函数。它应返回一个带有 id_token 属性的对象。这将作为 Authorization 头以格式 Bearer <id_token> 传递。
logOut: 当用户点击注销按钮时调用此函数。
authorize: 当用户进入 /admin 且已登录时调用此函数。用于确定用户是否有权访问管理页面。如果返回一个真值,用户被授权。如果返回一个假值,用户未被授权。
getSessionProvider: 返回一个包装 TinaCMS UI 的 React 上下文提供者。
import { AbstractAuthProvider } from 'tinacms'export class CustomAuthProvider extends AbstractAuthProvider {constructor() {super()// 在这里进行任何设置}async authenticate(props?: {}): Promise<any> {// 在这里进行任何认证}async getToken() {// 在这里返回令牌。令牌将作为 Authorization 头以格式 `Bearer <token>` 传递}async getUser() {// 返回一个真值,用户已登录;如果返回一个假值,用户未登录。}async logout() {// 在这里执行任何注销逻辑}async authorize(context?: any): Promise<any> {// 在这里执行任何授权逻辑}getSessionProvider() {// 如果不需要,可以删除 getSessionProvider// 可选地返回一个 React 上下文提供者来包装管理页面}}
现在您可以将自定义认证提供者添加到您的配置文件中:
export default defineConfig({authProvider: isLocal ? new LocalAuthProvider() : new CustomAuthProvider(),//...})
TinaNodeBackend 接受一个 authProvider 属性。
export interface BackendAuthProvider {initialize?: () => Promise<void>isAuthorized: (req: IncomingMessage,res: ServerResponse) => Promise<| {isAuthorized: true}| {isAuthorized: falseerrorMessage: stringerrorCode: number}>// 如果需要为后端附加任何额外的路由,可以使用此选项。例如,OAuth 的回调路由extraRoutes?: {[key: string]: {// 如果 secure 为 true,则在调用处理程序之前将调用 `isAuthorized` 函数secure?: booleanhandler: (req: IncomingMessage, res: ServerResponse) => Promise<void>}}}
此接口必须传递给 TinaNodeBackend 的 authProvider 属性。您可以通过调用 req.headers.authorization 从请求中获取令牌。此令牌应在 isAuthorized 函数中进行验证。
const CustomBackendAuth = () => {return {isAuthorized: async (req, res) => {const token = req.headers.authorization// 在这里验证令牌return {isAuthorized: true,}},}}
有关如何执行此操作的示例,请参见 Auth.js 后端。
一旦创建了实现 BackendAuthProvider 接口的对象,您可以将其传递给 TinaNodeBackend 的 authProvider 属性。
/pages/api/tina/[...routes].{ts,js}
const handler = TinaNodeBackend({authProvider: isLocal ? LocalBackendAuthProvider() : CustomBackendAuth(),databaseClient,})