Description
CompositeAuth proxies SSO (getLoginUrl, handleCallback), Session (createSession, validateSession), and User (getCurrentUser, getUser) interfaces from sub-providers, but does not proxy the credentials signIn interface. When using new CompositeAuth([apiKeyProvider, credentialsProvider]), the resulting auth object has no signIn method, causing:
implementsInterface(auth, "signIn") returns false
buildCapabilities() returns login: null
- Mastra Studio shows "Authentication Required — no login method is configured"
POST /api/auth/credentials/sign-in returns 404
Steps to Reproduce
const auth = new CompositeAuth([simpleApiAuth, studioAuthProvider]);
// typeof auth.signIn === "undefined" ← should be a function
const capabilities = await buildCapabilities(auth, request);
// capabilities.login === null ← should be { type: "credentials" }
Root Cause
packages/core/src/server/composite-auth.ts — CompositeAuth constructor checks for three provider interfaces but is missing isCredentialsProvider:
isSSOProvider → getLoginUrl / handleCallback / getLoginButtonConfig
isSessionProvider → createSession / validateSession / getSessionIdFromRequest
isUserProvider → getCurrentUser / getUser
isCredentialsProvider → (missing) ← signIn / isSignUpEnabled not proxied
PR #16664 fixed the duck-typing detection for the three existing interfaces but did not add credentials support.
Expected Behavior
const auth = new CompositeAuth([simpleApiAuth, studioAuthProvider]);
typeof auth.signIn === "function"; // true — delegated from studioAuthProvider
Proposed Fix
Three additions to packages/core/src/server/composite-auth.ts:
- Guard function:
function isCredentialsProvider(p: unknown): boolean {
return p !== null && typeof p === "object" && typeof (p as any).signIn === "function";
}
- In
CompositeAuth constructor, after the isUserProvider block:
if (!providers.some(isCredentialsProvider)) {
(this as any).signIn = void 0;
(this as any).isSignUpEnabled = void 0;
} else {
const credProvider = providers.find(isCredentialsProvider)!;
(this as any).signIn = credProvider.signIn.bind(credProvider);
(this as any).isSignUpEnabled = () =>
typeof credProvider.isSignUpEnabled === "function"
? credProvider.isSignUpEnabled()
: false;
}
Workaround
Manually patch the CompositeAuth instance after construction:
const auth = new CompositeAuth([simpleApiAuth, studioAuthProvider]);
(auth as any).signIn = studioAuthProvider.signIn.bind(studioAuthProvider);
(auth as any).isSignUpEnabled = () => studioAuthProvider.isSignUpEnabled();
Related
Description
CompositeAuthproxies SSO (getLoginUrl,handleCallback), Session (createSession,validateSession), and User (getCurrentUser,getUser) interfaces from sub-providers, but does not proxy the credentialssignIninterface. When usingnew CompositeAuth([apiKeyProvider, credentialsProvider]), the resulting auth object has nosignInmethod, causing:implementsInterface(auth, "signIn")returnsfalsebuildCapabilities()returnslogin: nullPOST /api/auth/credentials/sign-inreturns 404Steps to Reproduce
Root Cause
packages/core/src/server/composite-auth.ts—CompositeAuthconstructor checks for three provider interfaces but is missingisCredentialsProvider:PR #16664 fixed the duck-typing detection for the three existing interfaces but did not add credentials support.
Expected Behavior
Proposed Fix
Three additions to
packages/core/src/server/composite-auth.ts:CompositeAuthconstructor, after theisUserProviderblock:Workaround
Manually patch the
CompositeAuthinstance after construction:Related