@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio
275 lines • 10.3 kB
JavaScript
// src/lib/auth/providers/auth0.ts
import { BaseAuthProvider } from "./BaseAuthProvider.js";
import { AuthError } from "../errors.js";
import { logger } from "../../utils/logger.js";
import { createProxyFetch } from "../../proxy/proxyFetch.js";
import * as jose from "jose";
/**
* Auth0 Authentication Provider
*
* Supports JWT validation with JWKS for Auth0-issued tokens.
* Uses jose library for JWT verification against Auth0's JWKS endpoint.
*
* Features:
* - JWT validation with JWKS
* - User profile fetching (requires Management API token)
* - Role and permission extraction from token claims
*
* @example
* ```typescript
* const auth0 = new Auth0Provider({
* type: "auth0",
* domain: "your-tenant.auth0.com",
* clientId: "your-client-id",
* audience: "https://your-api.example.com"
* });
*
* const result = await auth0.authenticateToken(bearerToken);
* if (result.valid) {
* console.log("Authenticated user:", result.user);
* }
* ```
*/
export class Auth0Provider extends BaseAuthProvider {
type = "auth0";
domain;
clientId;
audience;
rolesNamespace;
permissionsNamespace;
jwks = null;
constructor(config) {
super(config);
if (!config.domain) {
throw AuthError.create("CONFIGURATION_ERROR", "Auth0 domain is required", { details: { missingFields: ["domain"] } });
}
if (!config.clientId) {
throw AuthError.create("CONFIGURATION_ERROR", "Auth0 clientId is required", { details: { missingFields: ["clientId"] } });
}
this.domain = config.domain;
this.clientId = config.clientId;
this.audience = config.audience;
// Allow custom namespaces for roles/permissions claims.
// If no namespace is configured, fall back to standard "roles" / "permissions" claims.
this.rolesNamespace = config.options?.rolesNamespace;
this.permissionsNamespace = config.options?.permissionsNamespace;
}
/**
* Initialize JWKS for JWT verification
*/
async initialize() {
try {
const jwksUrl = new URL(`https://${this.domain}/.well-known/jwks.json`);
this.jwks = jose.createRemoteJWKSet(jwksUrl);
logger.debug(`Auth0 provider initialized for domain: ${this.domain}`);
}
catch (error) {
throw AuthError.create("PROVIDER_INIT_FAILED", "Failed to initialize Auth0 JWKS", { cause: error instanceof Error ? error : new Error(String(error)) });
}
}
/**
* Validate Auth0 JWT token
*/
async authenticateToken(token, _context) {
if (!this.jwks) {
await this.initialize();
}
try {
if (!this.jwks) {
return {
valid: false,
error: "Auth0 JWKS not initialized",
};
}
const { payload } = await jose.jwtVerify(token, this.jwks, {
issuer: `https://${this.domain}/`,
audience: this.audience,
});
const auth0Payload = payload;
// Validate audience / authorized party against clientId
if (this.audience) {
const aud = auth0Payload.aud;
const audArray = Array.isArray(aud) ? aud : [aud];
if (!audArray.includes(this.audience)) {
return {
valid: false,
error: `Token audience does not match expected audience: ${this.audience}`,
};
}
}
if (this.clientId) {
const aud = auth0Payload.aud;
const azp = payload.azp;
const audArray = Array.isArray(aud) ? aud : [aud];
if (azp) {
if (azp !== this.clientId) {
return {
valid: false,
error: `Token azp claim "${azp}" does not match clientId "${this.clientId}"`,
};
}
}
else if (!audArray.includes(this.clientId)) {
return {
valid: false,
error: `Token audience does not include clientId "${this.clientId}"`,
};
}
}
// Extract roles: use custom namespace if configured, otherwise standard "roles" claim
const rolesKey = this.rolesNamespace ?? "roles";
const permissionsKey = this.permissionsNamespace ?? "permissions";
const roles = payload[rolesKey] || auth0Payload.roles || [];
const permissions = payload[permissionsKey] || auth0Payload.permissions || [];
// Extract user information from token
const user = {
id: auth0Payload.sub,
email: auth0Payload.email,
name: auth0Payload.name,
picture: auth0Payload.picture,
emailVerified: auth0Payload.email_verified,
roles,
permissions,
metadata: {
iss: auth0Payload.iss,
aud: auth0Payload.aud,
},
};
return {
valid: true,
payload: payload,
user,
expiresAt: new Date(auth0Payload.exp * 1000),
tokenType: "jwt",
};
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
logger.warn("Auth0 token validation failed:", message);
return {
valid: false,
error: message,
};
}
}
/**
* Fetch user profile from Auth0 Management API
* Note: Requires AUTH0_MANAGEMENT_TOKEN environment variable
*/
async getUser(userId) {
const managementToken = process.env.AUTH0_MANAGEMENT_TOKEN;
if (!managementToken) {
logger.warn("AUTH0_MANAGEMENT_TOKEN not set, cannot fetch user profile");
return null;
}
try {
const proxyFetch = createProxyFetch();
const response = await proxyFetch(`https://${this.domain}/api/v2/users/${encodeURIComponent(userId)}`, {
headers: {
Authorization: `Bearer ${managementToken}`,
},
});
if (!response.ok) {
if (response.status === 404) {
return null;
}
throw AuthError.create("PROVIDER_ERROR", `Auth0 API returned ${response.status}`, { details: { statusCode: response.status } });
}
const data = (await response.json());
return {
id: data.user_id,
email: data.email,
name: data.name,
picture: data.picture,
emailVerified: data.email_verified,
roles: data.app_metadata?.roles ||
[],
permissions: data.app_metadata
?.permissions || [],
createdAt: data.created_at
? new Date(data.created_at)
: undefined,
lastLoginAt: data.last_login
? new Date(data.last_login)
: undefined,
metadata: data.user_metadata,
};
}
catch (error) {
logger.error("Failed to fetch Auth0 user:", error);
throw error;
}
}
/**
* Get user by email from Auth0 Management API
*/
async getUserByEmail(email) {
const managementToken = process.env.AUTH0_MANAGEMENT_TOKEN;
if (!managementToken) {
logger.warn("AUTH0_MANAGEMENT_TOKEN not set, cannot fetch user by email");
return null;
}
try {
const proxyFetch = createProxyFetch();
const response = await proxyFetch(`https://${this.domain}/api/v2/users-by-email?email=${encodeURIComponent(email)}`, {
headers: {
Authorization: `Bearer ${managementToken}`,
},
});
if (!response.ok) {
throw AuthError.create("PROVIDER_ERROR", `Auth0 API returned ${response.status}`, { details: { statusCode: response.status } });
}
const users = (await response.json());
if (users.length === 0) {
return null;
}
const data = users[0];
return {
id: data.user_id,
email: data.email,
name: data.name,
picture: data.picture,
emailVerified: data.email_verified,
roles: data.app_metadata?.roles ||
[],
permissions: data.app_metadata
?.permissions || [],
createdAt: data.created_at
? new Date(data.created_at)
: undefined,
lastLoginAt: data.last_login
? new Date(data.last_login)
: undefined,
metadata: data.user_metadata,
};
}
catch (error) {
logger.error("Failed to fetch Auth0 user by email:", error);
throw error;
}
}
/**
* Health check
*/
async healthCheck() {
try {
const proxyFetch = createProxyFetch();
const response = await proxyFetch(`https://${this.domain}/.well-known/openid-configuration`);
return {
healthy: response.ok,
providerConnected: response.ok,
sessionStorageHealthy: true,
error: response.ok ? undefined : `HTTP ${response.status}`,
};
}
catch (error) {
return {
healthy: false,
providerConnected: false,
sessionStorageHealthy: true,
error: error instanceof Error ? error.message : String(error),
};
}
}
}
//# sourceMappingURL=auth0.js.map