Skip to main content

复合认证类

🌐 CompositeAuth Class

CompositeAuth 类允许你将多个身份验证提供程序组合到一个身份验证处理器中。它会按顺序尝试每个提供程序,直到其中一个成功为止。

🌐 The CompositeAuth class allows you to combine multiple authentication providers into a single auth handler. It tries each provider in order until one succeeds.

用例
Direct link to 用例

🌐 Use Cases

  • 支持 API 密钥和 OAuth 令牌
  • 在不影响现有客户端的情况下在认证提供商之间迁移
  • 允许使用多个身份提供商(例如,网页使用 Clerk,集成使用 API 密钥)
  • 逐步推出新的身份验证方法

安装
Direct link to 安装

🌐 Installation

CompositeAuth 已包含在 @mastra/core 中,无需额外安装任何包。

🌐 CompositeAuth is included in @mastra/core, no additional packages required.

import { CompositeAuth } from '@mastra/core/server';

使用示例
Direct link to 使用示例

🌐 Usage Example

将 SimpleAuth(用于 API 密钥)与 Clerk(用于用户会话)结合使用:

🌐 Combine SimpleAuth (for API keys) with Clerk (for user sessions):

src/mastra/index.ts
import { Mastra } from '@mastra/core';
import { CompositeAuth, SimpleAuth } from '@mastra/core/server';
import { MastraAuthClerk } from '@mastra/auth-clerk';

// API key users
type ApiKeyUser = {
id: string;
name: string;
type: 'api-key';
};

const apiKeyAuth = new SimpleAuth<ApiKeyUser>({
tokens: {
'sk-integration-key-123': {
id: 'integration-1',
name: 'CI/CD Pipeline',
type: 'api-key',
},
},
});

// Clerk users (from web app)
const clerkAuth = new MastraAuthClerk({
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
secretKey: process.env.CLERK_SECRET_KEY,
jwksUri: process.env.CLERK_JWKS_URI,
});

export const mastra = new Mastra({
server: {
auth: new CompositeAuth([apiKeyAuth, clerkAuth]),
},
});

工作原理
Direct link to 工作原理

🌐 How It Works

当收到请求时,CompositeAuth:

🌐 When a request comes in, CompositeAuth:

  1. Authorization 头部提取令牌
  2. 按顺序尝试每个提供商的 authenticateToken() 方法
  3. 返回第一个成功的提供商的用户
  4. 如果所有提供商都失败,则返回 null(401 未授权)

对于授权,它会依次调用每个提供商的 authorizeUser() 方法,直到有一个返回 true

🌐 For authorization, it calls each provider's authorizeUser() method until one returns true.

// Pseudocode of CompositeAuth behavior
async authenticateToken(token, request) {
for (const provider of this.providers) {
const user = await provider.authenticateToken(token, request);
if (user) return user; // First match wins
}
return null; // All providers failed
}

提供商订单
Direct link to 提供商订单

🌐 Provider Order

提供程序的顺序很重要。为了更好的性能,请将最常用的身份验证方法放在第一位:

🌐 The order of providers matters. Place the most common authentication method first for better performance:

// If most requests use Clerk, put it first
new CompositeAuth([
clerkAuth, // Checked first (most common)
apiKeyAuth, // Checked second (less common)
]);

// If most requests use API keys, put it first
new CompositeAuth([
apiKeyAuth, // Checked first (most common)
clerkAuth, // Checked second (less common)
]);

多个 OAuth 提供商
Direct link to 多个 OAuth 提供商

🌐 Multiple OAuth Providers

支持来自不同身份提供商的用户:

🌐 Support users from different identity providers:

import { CompositeAuth } from '@mastra/core/server';
import { MastraAuthClerk } from '@mastra/auth-clerk';
import { MastraAuthAuth0 } from '@mastra/auth-auth0';

const clerkAuth = new MastraAuthClerk({
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
secretKey: process.env.CLERK_SECRET_KEY,
jwksUri: process.env.CLERK_JWKS_URI,
});

const auth0Auth = new MastraAuthAuth0({
domain: process.env.AUTH0_DOMAIN,
audience: process.env.AUTH0_AUDIENCE,
});

export const mastra = new Mastra({
server: {
auth: new CompositeAuth([clerkAuth, auth0Auth]),
},
});

迁移示例
Direct link to 迁移示例

🌐 Migration Example

在保持向后兼容的同时,从 JWT 迁移到 Clerk:

🌐 Migrate from JWT to Clerk while maintaining backwards compatibility:

import { CompositeAuth } from '@mastra/core/server';
import { MastraJwtAuth } from '@mastra/auth';
import { MastraAuthClerk } from '@mastra/auth-clerk';

// Legacy JWT auth (existing clients)
const legacyAuth = new MastraJwtAuth({
secret: process.env.JWT_SECRET,
});

// New Clerk auth (new clients)
const clerkAuth = new MastraAuthClerk({
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
secretKey: process.env.CLERK_SECRET_KEY,
jwksUri: process.env.CLERK_JWKS_URI,
});

// Support both during migration
export const mastra = new Mastra({
server: {
auth: new CompositeAuth([
clerkAuth, // New auth method (preferred)
legacyAuth, // Legacy support
]),
},
});

使用自定义提供程序
Direct link to 使用自定义提供程序

🌐 With Custom Providers

将内置提供程序与自定义实现结合起来:

🌐 Combine built-in providers with custom implementations:

import { CompositeAuth, SimpleAuth } from '@mastra/core/server';
import { MyCustomAuth } from './my-custom-auth';

const apiKeyAuth = new SimpleAuth({
tokens: {
'sk-key-123': { id: 'user-1', name: 'API User' },
},
});

const customAuth = new MyCustomAuth({
apiUrl: process.env.CUSTOM_AUTH_URL,
});

export const mastra = new Mastra({
server: {
auth: new CompositeAuth([apiKeyAuth, customAuth]),
},
});

错误处理
Direct link to 错误处理

🌐 Error Handling

CompositeAuth 会悄悄地捕获来自各个提供商的错误,并切换到下一个提供商。这可以防止某个失败的提供商阻碍认证:

🌐 CompositeAuth silently catches errors from individual providers and moves to the next one. This prevents one failing provider from blocking authentication:

// If clerkAuth throws an error, apiKeyAuth still gets tried
new CompositeAuth([clerkAuth, apiKeyAuth]);

要调试身份验证问题,请在自定义提供程序中添加日志记录,或检查各个提供程序的配置。

🌐 To debug authentication issues, add logging to your custom providers or check individual provider configurations.

限制
Direct link to 限制

🌐 Limitations

  • 所有提供商都共享来自 Authorization 头的相同令牌
  • 用户类型可能因提供商而异(如有需要,可使用区分联合类型)
  • 没有内置方法来识别哪个提供商进行了身份验证请求

处理不同类型的用户
Direct link to 处理不同类型的用户

🌐 Handling Different User Types

当提供商返回不同的用户类型时,使用区分联合类型:

🌐 When providers return different user types, use a discriminated union:

type ApiKeyUser = {
type: 'api-key';
id: string;
name: string;
};

type ClerkUser = {
type: 'clerk';
sub: string;
email: string;
};

type User = ApiKeyUser | ClerkUser;

// In your application code
function handleUser(user: User) {
if (user.type === 'api-key') {
console.log('API key user:', user.name);
} else {
console.log('Clerk user:', user.email);
}
}

🌐 Related