Authdog

Agents quickstart

Last updated Oct 27, 2026
View as Markdown

Outcome: an agent identity that can mint a client_credentials token and call one protected route. About five minutes from an empty environment.

Self-serve. Agents is open in every environment. Usage counts against your plan's agent-run quota. Do not put a human cookie or PAT in the agent runtime.

0. Prerequisites

  • An Authdog tenant, project, and environment.
  • A token endpoint from the environment OIDC metadata (/oauth2/token).

1. Register an agent

In the console, open Agents (/dashboard/agents):

  1. New agent → Create new agent identity.
  2. Name it. Give it the mcp:invoke scope. Optional: allowed tools (* or globs).
  3. Copy the client ID and client secret. The secret is shown once.

This provisions a confidential OIDC client and a trust-store row whose subject is that client ID.

REST equivalent (after you have a management token):

POST /v1/tenants/{tenantId}/environments/{environmentId}/mcp/trust-store

The wizard is the path that also creates the OIDC client. REST registers a subject that already authenticates.

2. Exchange credentials for a token

Ask for the mcp:invoke scope and name the MCP server as the resource. The resource must be an https URL. With both, Authdog mints a signed JWT whose audience is that server. Without them the token is opaque and carries no audience.

curl -X POST "$TOKEN_ENDPOINT" \
  -u "$AUTHDOG_CLIENT_ID:$AUTHDOG_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "scope=mcp:invoke" \
  --data-urlencode "resource=https://mcp.example.com"

You get access_token, token_type, expires_in. No refresh token. Repeat the exchange before expiry.

A revoked agent whose subject is this client_id gets 401 on this call. Tokens already issued stay valid until expires_in unless the resource server runs trust-store enforce.

3. Call a protected route

Authorization: Bearer <access_token>

For an HTTP API, use a backend SDK require_auth gate (Express, FastAPI).

For an MCP server in Node.js, install the verifier and the MCP SDK:

npm install @authdog/mcp-sdk @modelcontextprotocol/sdk express

Then guard the /mcp route. Setting issuer verifies the JWT locally against your environment's keys, and audience rejects tokens minted for another server:

import express from "express"
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js"
import { AuthdogVerifier } from "@authdog/mcp-sdk"
import { createMcpTokenVerifier } from "@authdog/mcp-sdk/mcp"

const authdog = new AuthdogVerifier({
  baseUrl: "https://api.authdog.com",
  issuer: "https://api.authdog.com/oidc/<environmentId>",
  audience: "https://mcp.example.com",
})

const app = express()

app.use(
  "/mcp",
  requireBearerAuth({
    verifier: createMcpTokenVerifier(authdog, {
      resource: "https://mcp.example.com",
    }),
    requiredScopes: ["mcp:invoke"],
    resourceMetadataUrl:
      "https://mcp.example.com/.well-known/oauth-protected-resource",
    expectedResource: "https://mcp.example.com",
  }),
)

app.listen(3000)

See the Node.js SDK for every option. To also enforce allowed tools and per-tool decisions, add the private runtime guard described in MCP SDK, or run examples/mcp-auth-sample with MCP_TRUST_STORE_MODE=enforce and MCP_AUTHZ_MODE=enforce.

Agent frameworks puts this same bearer on the hook that framework already exposes.

4. Verify

  • Token exchange without credentials → 401.
  • GET the protected route without a bearer → 401.
  • With the bearer → the caller is the agent, not a human session.

Next

Learn more