Auth0 provides enterprise-grade authentication and authorization with support for social logins, enterprise connections, and custom identity providers.
Installation
npm install @mastra/auth-auth0
Configuration
Create Auth0 Application
Sign up at Auth0 and create an API application. Get your:
Domain (e.g., your-tenant.us.auth0.com)
API Identifier (Audience)
Set Environment Variables
AUTH0_DOMAIN = your-tenant.us.auth0.com
AUTH0_AUDIENCE = https://your-api.com
Import and Configure
import { MastraAuthAuth0 } from '@mastra/auth-auth0' ;
import { Mastra } from '@mastra/core' ;
const auth = new MastraAuthAuth0 ();
const mastra = new Mastra ({
server: {
auth ,
},
});
Configuration Options
Auth0 domain. Defaults to process.env.AUTH0_DOMAIN
Auth0 API identifier. Defaults to process.env.AUTH0_AUDIENCE
Usage Examples
Basic Setup
import { Mastra } from '@mastra/core' ;
import { MastraAuthAuth0 } from '@mastra/auth-auth0' ;
import { MastraServer } from '@mastra/hono' ;
import { Hono } from 'hono' ;
const mastra = new Mastra ({
server: {
auth: new MastraAuthAuth0 (),
},
});
const app = new Hono ();
const server = new MastraServer ({ mastra , app });
Explicit Configuration
const auth = new MastraAuthAuth0 ({
domain: 'your-tenant.us.auth0.com' ,
audience: 'https://your-api.com' ,
name: 'auth0-provider' ,
});
const mastra = new Mastra ({
server: {
auth ,
},
});
Custom Authorization
const auth = new MastraAuthAuth0 ({
authorizeUser : async ( user ) => {
// Check token expiration
if ( user . exp && user . exp * 1000 < Date . now ()) {
return false ;
}
// Check custom claims
const permissions = user [ 'https://your-app.com/permissions' ] || [];
return permissions . includes ( 'api:access' );
},
});
const mastra = new Mastra ({
server: {
auth ,
},
});
Client Integration
React with Auth0
import { Auth0Provider , useAuth0 } from '@auth0/auth0-react' ;
export default function App () {
return (
< Auth0Provider
domain = "your-tenant.us.auth0.com"
clientId = "your-client-id"
authorizationParams = { {
redirect_uri: window . location . origin ,
audience: 'https://your-api.com' ,
} }
>
< MyApp />
</ Auth0Provider >
);
}
function MyApp () {
const { isAuthenticated , loginWithRedirect , logout , user } = useAuth0 ();
if ( ! isAuthenticated ) {
return < button onClick = { () => loginWithRedirect () } > Log in </ button > ;
}
return (
< div >
< p > Welcome { user ?. name } </ p >
< button onClick = { () => logout () } > Log out </ button >
< MyMastraComponent />
</ div >
);
}
Making Authenticated Requests
import { useAuth0 } from '@auth0/auth0-react' ;
function MyMastraComponent () {
const { getAccessTokenSilently } = useAuth0 ();
const callMastraAPI = async () => {
const token = await getAccessTokenSilently ({
authorizationParams: {
audience: 'https://your-api.com' ,
},
});
const response = await fetch ( 'http://localhost:4111/api/mastra/agents' , {
headers: {
'Authorization' : `Bearer ${ token } ` ,
},
});
const data = await response . json ();
console . log ( data );
};
return < button onClick ={ callMastraAPI }> Call Mastra </ button > ;
}
Token Verification
Mastra automatically verifies Auth0 JWT tokens:
Token Extraction : Bearer token from Authorization header
JWKS Verification : Validates signature using Auth0’s JWKS endpoint
Issuer Validation : Checks token issuer matches your domain
Audience Validation : Verifies audience matches your API identifier
Expiration Check : Ensures token is not expired
User Object
The authenticated user object contains JWT claims:
interface Auth0User {
sub : string ; // User ID (e.g., 'auth0|123456')
iss : string ; // Issuer (https://your-domain.auth0.com/)
aud : string ; // Audience
exp : number ; // Expiration timestamp
iat : number ; // Issued at timestamp
azp ?: string ; // Authorized party (client ID)
scope ?: string ; // Granted scopes
// Custom claims with namespace
'https://your-app.com/roles' ?: string [];
'https://your-app.com/permissions' ?: string [];
}
Custom Claims
Add custom claims using Auth0 Actions:
// Auth0 Action: Add custom claims
exports . onExecutePostLogin = async ( event , api ) => {
const namespace = 'https://your-app.com' ;
api . accessToken . setCustomClaim ( ` ${ namespace } /roles` , event . user . app_metadata . roles || []);
api . accessToken . setCustomClaim ( ` ${ namespace } /permissions` , event . user . app_metadata . permissions || []);
};
Access in authorization:
const auth = new MastraAuthAuth0 ({
authorizeUser : async ( user ) => {
const roles = user [ 'https://your-app.com/roles' ] || [];
return roles . includes ( 'admin' ) || roles . includes ( 'user' );
},
});
Authentication Flow
Best Practices
Use API Identifier Always specify an audience (API identifier) to get access tokens, not ID tokens.
Namespace Custom Claims Use namespaced URLs for custom claims to avoid conflicts: 'https://your-app.com/roles'
Scope Management Define and check scopes for fine-grained permissions: scope : 'read:agents write:workflows'
Token Expiration Configure appropriate token lifetimes in Auth0 Dashboard:
Access tokens: 1-24 hours
Refresh tokens: 7-30 days
Auth0 Features
Authentication Methods
Username/password
Social logins (Google, GitHub, etc.)
Enterprise connections (SAML, AD)
Passwordless (email, SMS)
Multi-factor authentication
Advanced Features
Actions : Customize authentication flow
Rules : Legacy custom logic
Organizations : Multi-tenant B2B support
RBAC : Role-based access control
Attack Protection : Brute force & bot detection
Troubleshooting
Invalid Audience
Ensure your API is registered in Auth0 and the audience matches:
audience : 'https://your-api.com' // Must match API identifier
CORS Errors
Add your application URL to Auth0 Dashboard:
Allowed Callback URLs
Allowed Logout URLs
Allowed Web Origins
Token Verification Failed
Check that:
Domain is correct (no https:// prefix)
Token includes required audience
Token is not expired
Clerk Modern user management alternative
better-auth Self-hosted authentication framework
Auth0 Docs Official Auth0 documentation
Auth0 Dashboard Manage applications and APIs