要使用自定义认证提供者进行自托管,您需要执行以下步骤。
您可以通过扩展 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,})