Composite Auth - Combining Multiple Authentication Providers in Mastra
Trust: ★★★☆☆ (0.90) · 0 validations · developer_reference
Published: 2026-05-10 · Source: crawler_authoritative
Tình huống
Mastra SDK documentation for combining multiple authentication providers into a single auth handler, targeting developers implementing auth in their applications.
Insight
The CompositeAuth class allows combining multiple authentication providers into a single auth handler that tries each provider in order until one succeeds. It is included in @mastra/core (no additional packages required). The class works by extracting the token from the Authorization header, then iterating through each provider’s authenticateToken() method—returning the user from the first provider that succeeds, or null (401 Unauthorized) if all providers fail. For authorization, it calls each provider’s authorizeUser() method until one returns true. The provider order matters for performance—place the most common authentication method first. CompositeAuth silently catches errors from individual providers and moves to the next one, preventing one failing provider from blocking authentication. Limitations include: all providers share the same token from the Authorization header, user types may differ between providers (use discriminated unions), and no built-in way to identify which provider authenticated a request. Built-in providers include SimpleAuth for API keys, MastraAuthClerk for Clerk, MastraAuthAuth0 for Auth0, and MastraJwtAuth for JWT. Custom providers can be implemented and combined with built-in ones.
Hành động
Import CompositeAuth from ‘@mastra/core/server’. Create instances of desired auth providers (e.g., SimpleAuth for API keys, MastraAuthClerk for Clerk sessions). Pass an array of provider instances to CompositeAuth in the desired order. Assign the CompositeAuth instance to server.auth in your Mastra constructor. For different user types across providers, use a discriminated union type to handle them in application code. To debug auth issues, add logging to custom providers or check individual provider configurations.
Kết quả
Returns the authenticated user from the first provider that successfully validates the token, or null (401 Unauthorized) if all providers fail.
Điều kiện áp dụng
Included in @mastra/core, no additional packages required. Available for use with any Mastra-compatible auth providers.
Nội dung gốc (Original)
Composite Auth
The CompositeAuth class allows you to combine multiple authentication providers into a single auth handler. It tries each provider in order until one succeeds.
Use cases
- Support both API keys and OAuth tokens
- Migrate between auth providers without breaking existing clients
- Allow multiple identity providers (e.g., Clerk for web, API keys for integrations)
- Gradual rollout of new authentication methods
Installation
CompositeAuth is included in @mastra/core, no additional packages required.
import { CompositeAuth } from '@mastra/core/server'Usage example
Combine SimpleAuth (for API keys) with Clerk (for user sessions):
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]),
},
})How it works
When a request comes in, CompositeAuth:
- Extracts the token from the
Authorizationheader - Tries each provider’s
authenticateToken()method in order - Returns the user from the first provider that succeeds
- Returns
null(401 Unauthorized) if all providers fail
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
}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)
])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]),
},
})Migration example
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
]),
},
})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]),
},
})Error handling
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.
Limitations
- All providers share the same token from the
Authorizationheader - User types may differ between providers (use discriminated unions if needed)
- No built-in way to identify which provider authenticated a request
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)
}
}Liên kết
- Nền tảng: Dev Framework · Mastra
- Nguồn: https://mastra.ai/docs/server/auth/composite-auth
Xem thêm: