Mastra keeps its own auth hook. Authdog stays the identity provider. The sample attaches an agent access token there and refuses the run when that token is missing or userinfo rejects it.
Sample: mastra/typescript. Node.js. Package @mastra/[email protected].
Channel auth, machine credentials, tool checks, and instructions for this framework are the other pages under Mastra in AI.
The hook
export const mastra = new Mastra({
server: {
auth: {
authenticateToken: async (token) => {
const subject = await subjectIfAccepted(token)
if (!subject) return null
return { id: subject }
},
},
},
})Mastra routes stay public when server.auth is unset. With authenticateToken set, a route that does not opt out requires a user. Returning no user is unauthorized, and the response is 401. whoami returns id. A public route would have to set requiresAuth: false. This sample does not. Use the result the installed @mastra/core already treats as "no user" (null, or a rejected promise if that version requires it).
This is agent identity: client_credentials, then this hook. It is not Agent Sign-In. A browser sign-in does not replace the hook.
What you should see
A request with no bearer is 401. A bearer userinfo rejects is 401. The body has no subject.
A bearer userinfo accepts reaches whoami, which returns that subject.
npm test in mastra/typescript checks both. It does not call a model.
Configure
| Name | Purpose |
|---|---|
PK_AUTHDOG |
Public key on the Mastra server. Selects the identity host. |
Authorization |
Access token the caller presents. |
The shared exchange is in Agent frameworks. There is no refresh token. Repeat it before expires_in.
Related
| Read | To learn how to |
|---|---|
| Agent frameworks | Mint the bearer this hook checks |
| Claude Agent SDK | The previous hook |
| LlamaIndex Workflows | The next hook |
| Custom channel auth for Mastra | The same check, as the auth boundary |