Skip to main content

Method A — Client secret

The simplest M2M method: the service account holds an ID + shared secret, sent via HTTP Basic on each token request. Right for quick starts and simple deployments — see the comparison if you're unsure which method fits.

Create the service account

In the create dialog: name it, keep Client secret selected (the default), and click Create service account:

Create service account — client secret

Save the credentials — shown once

Client secret credentials

Copy both values into your service's .envthe secret won't be shown again (the dialog also confirms the wire mechanics: client_credentials grant with client_secret_basic auth — exactly what the SDK does for you):

AUTHSEC_ISSUER=https://mcpauthz.com
SA_CLIENT_ID=8a7c1107-...
SA_CLIENT_SECRET=<the secret you copied> # 64 hex chars — copy, don't retype
MCP_URL=https://your-mcp-server.example.com/mcp

Grant access (both methods need this — see below), then code:

import asyncio, os
from dotenv import load_dotenv
from authsec_sdk import AgentIdentity, ClientSecretAuth

load_dotenv()

async def main():
agent = AgentIdentity(
os.environ["AUTHSEC_ISSUER"],
os.environ["SA_CLIENT_ID"],
auth=ClientSecretAuth(os.environ["SA_CLIENT_SECRET"]),
)
async with agent:
token = await agent.access_for(
os.environ["MCP_URL"],
requested_scopes=["test_mcp:read", "test_mcp:tools:read"],
)
print("token:", token[:25], "…") # → Authorization: Bearer {token}

asyncio.run(main())

Both remaining steps are shared by every method: grant access · verify · troubleshooting