mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-28 02:10:38 +02:00
AuthKit: auto-bind token audience to resource URL (RFC 8707) (#3905)
This commit is contained in:
parent
c2dafc1c88
commit
82f310fe61
33 changed files with 265 additions and 114 deletions
36
examples/auth/authkit/README.md
Normal file
36
examples/auth/authkit/README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# AuthKit Example
|
||||
|
||||
Protects a FastMCP server with WorkOS AuthKit. The server binds the JWT
|
||||
`aud` claim to its own resource URL automatically — you just paste that same
|
||||
URL into the WorkOS Dashboard as a resource indicator.
|
||||
|
||||
## WorkOS Dashboard setup
|
||||
|
||||
In the WorkOS Dashboard for your project, go to **Connect → Configuration** and:
|
||||
|
||||
1. Under **MCP Auth**, enable **Dynamic Client Registration** (or **Client ID
|
||||
Metadata Document** if your MCP client supports it).
|
||||
2. Under **MCP resource indicators**, add `http://127.0.0.1:8000/mcp` as a
|
||||
valid resource indicator.
|
||||
|
||||
## Running
|
||||
|
||||
1. Set your AuthKit domain:
|
||||
|
||||
```bash
|
||||
export AUTHKIT_DOMAIN="https://your-app.authkit.app"
|
||||
```
|
||||
|
||||
2. Start the server. It logs the resource URL it's validating against —
|
||||
that's the URL that must match your dashboard resource indicator:
|
||||
|
||||
```bash
|
||||
python server.py
|
||||
```
|
||||
|
||||
3. In another terminal, run the client. Your browser will open for AuthKit
|
||||
authentication:
|
||||
|
||||
```bash
|
||||
python client.py
|
||||
```
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
"""AuthKit DCR server example for FastMCP.
|
||||
"""AuthKit server example for FastMCP.
|
||||
|
||||
This example demonstrates how to protect a FastMCP server with AuthKit DCR.
|
||||
Demonstrates an MCP server secured by WorkOS AuthKit. FastMCP binds the JWT
|
||||
audience to this server's resource URL automatically; you configure the same
|
||||
URL as an MCP resource indicator in the WorkOS Dashboard.
|
||||
|
||||
Required environment variables:
|
||||
- FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_AUTHKIT_DOMAIN: Your AuthKit domain (e.g., "https://your-app.authkit.app")
|
||||
- AUTHKIT_DOMAIN: Your AuthKit domain (e.g., "https://your-app.authkit.app")
|
||||
|
||||
To run:
|
||||
python server.py
|
||||
|
|
@ -16,10 +18,10 @@ from fastmcp.server.auth.providers.workos import AuthKitProvider
|
|||
|
||||
auth = AuthKitProvider(
|
||||
authkit_domain=os.getenv("AUTHKIT_DOMAIN") or "",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
)
|
||||
|
||||
mcp = FastMCP("AuthKit DCR Example Server", auth=auth)
|
||||
mcp = FastMCP("AuthKit Example Server", auth=auth)
|
||||
|
||||
|
||||
@mcp.tool
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# AuthKit DCR Example
|
||||
|
||||
Demonstrates FastMCP server protection with AuthKit Dynamic Client Registration.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Set your AuthKit domain:
|
||||
|
||||
```bash
|
||||
export AUTHKIT_DOMAIN="https://your-app.authkit.app"
|
||||
```
|
||||
|
||||
2. Run the server:
|
||||
|
||||
```bash
|
||||
python server.py
|
||||
```
|
||||
|
||||
3. In another terminal, run the client:
|
||||
|
||||
```bash
|
||||
python client.py
|
||||
```
|
||||
|
||||
The client will open your browser for AuthKit authentication.
|
||||
|
|
@ -10,7 +10,7 @@ Demonstrates FastMCP server protection with AWS Cognito OAuth.
|
|||
- Create an App Client in your User Pool
|
||||
- Configure the App Client settings:
|
||||
- Enable "Authorization code grant" flow
|
||||
- Add Callback URL: `http://localhost:8000/auth/callback`
|
||||
- Add Callback URL: `http://127.0.0.1:8000/auth/callback`
|
||||
- Configure OAuth scopes (at minimum: `openid`)
|
||||
- Note your User Pool ID, App Client ID, Client Secret, and Cognito Domain Prefix
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import asyncio
|
|||
|
||||
from fastmcp.client import Client
|
||||
|
||||
SERVER_URL = "http://localhost:8000/mcp"
|
||||
SERVER_URL = "http://127.0.0.1:8000/mcp"
|
||||
|
||||
|
||||
async def main():
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ auth = AWSCognitoProvider(
|
|||
or "eu-central-1",
|
||||
client_id=os.getenv("FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_ID") or "",
|
||||
client_secret=os.getenv("FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_SECRET") or "",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# redirect_path="/custom/callback"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ This example demonstrates how to use the Azure OAuth provider with FastMCP serve
|
|||
2. Click "New registration" and configure:
|
||||
- Name: Your app name
|
||||
- Supported account types: Choose based on your needs
|
||||
- Redirect URI: `http://localhost:8000/auth/callback` (Web platform)
|
||||
- Redirect URI: `http://127.0.0.1:8000/auth/callback` (Web platform)
|
||||
3. After creation, go to "Certificates & secrets" → "New client secret"
|
||||
4. Note these values from the Overview page:
|
||||
- Application (client) ID
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ auth = AzureProvider(
|
|||
client_secret=os.getenv("FASTMCP_SERVER_AUTH_AZURE_CLIENT_SECRET") or "",
|
||||
tenant_id=os.getenv("FASTMCP_SERVER_AUTH_AZURE_TENANT_ID")
|
||||
or "", # Required for single-tenant apps - get from Azure Portal
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
required_scopes=["read"],
|
||||
# required_scopes is automatically loaded from FASTMCP_SERVER_AUTH_AZURE_REQUIRED_SCOPES
|
||||
# At least one scope is required - use unprefixed scope names from your Azure App (e.g., ["read", "write"])
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Demonstrates FastMCP server protection with Clerk OAuth.
|
|||
- Create or select an application
|
||||
- Go to Developers > OAuth Applications
|
||||
- Create an OAuth application
|
||||
- Add Authorized redirect URI: `http://localhost:8000/auth/callback`
|
||||
- Add Authorized redirect URI: `http://127.0.0.1:8000/auth/callback`
|
||||
- Copy the Client ID and Client Secret
|
||||
- Note your instance domain (e.g., `saving-primate-16.clerk.accounts.dev`)
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ auth = ClerkProvider(
|
|||
domain=os.getenv("FASTMCP_SERVER_AUTH_CLERK_DOMAIN") or "",
|
||||
client_id=os.getenv("FASTMCP_SERVER_AUTH_CLERK_CLIENT_ID") or "",
|
||||
client_secret=os.getenv("FASTMCP_SERVER_AUTH_CLERK_CLIENT_SECRET") or "",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# redirect_path="/auth/callback", # Default path - change if using a different callback URL
|
||||
# Optional: specify required scopes (defaults to ["openid", "email", "profile"])
|
||||
# required_scopes=["openid", "email", "profile", "public_metadata"],
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Demonstrates FastMCP server protection with Discord OAuth.
|
|||
- Go to https://discord.com/developers/applications
|
||||
- Click "New Application" and give it a name
|
||||
- Go to OAuth2 in the left sidebar
|
||||
- Add a Redirect URL: `http://localhost:8000/auth/callback`
|
||||
- Add a Redirect URL: `http://127.0.0.1:8000/auth/callback`
|
||||
- Copy the Client ID and Client Secret
|
||||
|
||||
2. Set environment variables:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from fastmcp.server.auth.providers.discord import DiscordProvider
|
|||
auth = DiscordProvider(
|
||||
client_id=os.getenv("FASTMCP_SERVER_AUTH_DISCORD_CLIENT_ID") or "",
|
||||
client_secret=os.getenv("FASTMCP_SERVER_AUTH_DISCORD_CLIENT_SECRET") or "",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# redirect_path="/auth/callback", # Default path - change if using a different callback URL
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Demonstrates FastMCP server protection with GitHub OAuth.
|
|||
|
||||
1. Create a GitHub OAuth App:
|
||||
- Go to GitHub Settings > Developer settings > OAuth Apps
|
||||
- Set Authorization callback URL to: `http://localhost:8000/auth/callback`
|
||||
- Set Authorization callback URL to: `http://127.0.0.1:8000/auth/callback`
|
||||
- Copy the Client ID and Client Secret
|
||||
|
||||
2. Set environment variables:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import asyncio
|
|||
|
||||
from fastmcp.client import Client, OAuth
|
||||
|
||||
SERVER_URL = "http://localhost:8000/mcp"
|
||||
SERVER_URL = "http://127.0.0.1:8000/mcp"
|
||||
|
||||
|
||||
async def main():
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from fastmcp.server.auth.providers.github import GitHubProvider
|
|||
auth = GitHubProvider(
|
||||
client_id=os.getenv("FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID") or "",
|
||||
client_secret=os.getenv("FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRET") or "",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# redirect_path="/auth/callback", # Default path - change if using a different callback URL
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Demonstrates FastMCP server protection with Google OAuth.
|
|||
- Create or select a project
|
||||
- Go to APIs & Services > Credentials
|
||||
- Create OAuth 2.0 Client ID (Web application)
|
||||
- Add Authorized redirect URI: `http://localhost:8000/auth/callback`
|
||||
- Add Authorized redirect URI: `http://127.0.0.1:8000/auth/callback`
|
||||
- Copy the Client ID and Client Secret
|
||||
|
||||
2. Set environment variables:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from fastmcp.server.auth.providers.google import GoogleProvider
|
|||
auth = GoogleProvider(
|
||||
client_id=os.getenv("FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID") or "",
|
||||
client_secret=os.getenv("FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET") or "",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# redirect_path="/auth/callback", # Default path - change if using a different callback URL
|
||||
# Optional: specify required scopes
|
||||
# required_scopes=["openid", "https://www.googleapis.com/auth/userinfo.email"],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Demonstrates FastMCP server protection with Keycloak OAuth.
|
|||
|
||||
## Setup
|
||||
|
||||
1. Configure a Keycloak realm with Dynamic Client Registration enabled and a trusted host policy for your server URL (e.g. `http://localhost:8000/*`).
|
||||
1. Configure a Keycloak realm with Dynamic Client Registration enabled and a trusted host policy for your server URL (e.g. `http://127.0.0.1:8000/*`).
|
||||
|
||||
2. Set environment variables:
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import asyncio
|
|||
|
||||
from fastmcp import Client
|
||||
|
||||
SERVER_URL = "http://localhost:8000/mcp"
|
||||
SERVER_URL = "http://127.0.0.1:8000/mcp"
|
||||
|
||||
|
||||
async def main():
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ from fastmcp.server.dependencies import get_access_token
|
|||
|
||||
auth = KeycloakAuthProvider(
|
||||
realm_url=os.getenv("KEYCLOAK_REALM_URL") or "http://localhost:8080/realms/fastmcp",
|
||||
base_url="http://localhost:8000",
|
||||
# audience="http://localhost:8000", # Recommended for production
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# audience="http://127.0.0.1:8000", # Recommended for production
|
||||
)
|
||||
|
||||
mcp = FastMCP("Keycloak Example Server", auth=auth)
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ This example demonstrates mounting multiple OAuth-protected MCP servers in a sin
|
|||
|
||||
## URL Structure
|
||||
|
||||
- **GitHub MCP**: `http://localhost:8000/api/mcp/github/mcp`
|
||||
- **Google MCP**: `http://localhost:8000/api/mcp/google/mcp`
|
||||
- **GitHub MCP**: `http://127.0.0.1:8000/api/mcp/github/mcp`
|
||||
- **Google MCP**: `http://127.0.0.1:8000/api/mcp/google/mcp`
|
||||
|
||||
Discovery endpoints (RFC 8414 path-aware):
|
||||
- **GitHub**: `http://localhost:8000/.well-known/oauth-authorization-server/api/mcp/github`
|
||||
- **Google**: `http://localhost:8000/.well-known/oauth-authorization-server/api/mcp/google`
|
||||
- **GitHub**: `http://127.0.0.1:8000/.well-known/oauth-authorization-server/api/mcp/github`
|
||||
- **Google**: `http://127.0.0.1:8000/.well-known/oauth-authorization-server/api/mcp/google`
|
||||
|
||||
## Setup
|
||||
|
||||
|
|
@ -23,8 +23,8 @@ export FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
|||
```
|
||||
|
||||
Configure redirect URIs in each provider's developer console (note the `/api/mcp/{provider}` prefix since the servers are mounted):
|
||||
- GitHub: `http://localhost:8000/api/mcp/github/auth/callback/github`
|
||||
- Google: `http://localhost:8000/api/mcp/google/auth/callback/google`
|
||||
- GitHub: `http://127.0.0.1:8000/api/mcp/github/auth/callback/github`
|
||||
- Google: `http://127.0.0.1:8000/api/mcp/google/auth/callback/google`
|
||||
|
||||
## Running
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ application, each with its own provider. It showcases RFC 8414 path-aware discov
|
|||
where each server has its own authorization server metadata endpoint.
|
||||
|
||||
URL structure:
|
||||
- GitHub MCP: http://localhost:8000/api/mcp/github/mcp
|
||||
- Google MCP: http://localhost:8000/api/mcp/google/mcp
|
||||
- GitHub discovery: http://localhost:8000/.well-known/oauth-authorization-server/api/mcp/github
|
||||
- Google discovery: http://localhost:8000/.well-known/oauth-authorization-server/api/mcp/google
|
||||
- GitHub MCP: http://127.0.0.1:8000/api/mcp/github/mcp
|
||||
- Google MCP: http://127.0.0.1:8000/api/mcp/google/mcp
|
||||
- GitHub discovery: http://127.0.0.1:8000/.well-known/oauth-authorization-server/api/mcp/github
|
||||
- Google discovery: http://127.0.0.1:8000/.well-known/oauth-authorization-server/api/mcp/google
|
||||
|
||||
Required environment variables:
|
||||
- FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID: Your GitHub OAuth app client ID
|
||||
|
|
@ -31,7 +31,7 @@ from fastmcp.server.auth.providers.github import GitHubProvider
|
|||
from fastmcp.server.auth.providers.google import GoogleProvider
|
||||
|
||||
# Configuration
|
||||
ROOT_URL = "http://localhost:8000"
|
||||
ROOT_URL = "http://127.0.0.1:8000"
|
||||
API_PREFIX = "/api/mcp"
|
||||
|
||||
# --- GitHub OAuth Server ---
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Create a `.env` file:
|
|||
PROPELAUTH_AUTH_URL=https://auth.yourdomain.com
|
||||
PROPELAUTH_INTROSPECTION_CLIENT_ID=your-client-id
|
||||
PROPELAUTH_INTROSPECTION_CLIENT_SECRET=your-client-secret
|
||||
BASE_URL=http://localhost:8000/
|
||||
BASE_URL=http://127.0.0.1:8000/
|
||||
# Optional: additional scopes tokens must include (comma-separated)
|
||||
# PROPELAUTH_REQUIRED_SCOPES=read:user_data
|
||||
```
|
||||
|
|
@ -50,7 +50,7 @@ Start the server:
|
|||
uv run python server.py
|
||||
```
|
||||
|
||||
The server will start on `http://localhost:8000/mcp` with PropelAuth OAuth authentication enabled.
|
||||
The server will start on `http://127.0.0.1:8000/mcp` with PropelAuth OAuth authentication enabled.
|
||||
|
||||
Test with client:
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Required environment variables:
|
|||
|
||||
Optional:
|
||||
- PROPELAUTH_REQUIRED_SCOPES: Comma-separated scopes tokens must include
|
||||
- BASE_URL: Public URL where the FastMCP server is exposed (defaults to `http://localhost:8000/`)
|
||||
- BASE_URL: Public URL where the FastMCP server is exposed (defaults to `http://127.0.0.1:8000/`)
|
||||
|
||||
To run:
|
||||
python server.py
|
||||
|
|
@ -29,7 +29,7 @@ auth = PropelAuthProvider(
|
|||
auth_url=os.environ["PROPELAUTH_AUTH_URL"],
|
||||
introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"],
|
||||
introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"],
|
||||
base_url=os.getenv("BASE_URL", "http://localhost:8000/"),
|
||||
base_url=os.getenv("BASE_URL", "http://127.0.0.1:8000/"),
|
||||
)
|
||||
|
||||
mcp = FastMCP("PropelAuth OAuth Example Server", auth=auth)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Create a `.env` file:
|
|||
# Required Scalekit credentials
|
||||
SCALEKIT_ENVIRONMENT_URL=<YOUR_APP_ENVIRONMENT_URL>
|
||||
SCALEKIT_RESOURCE_ID=<YOUR_APP_RESOURCE_ID> # res_926EXAMPLE5878
|
||||
BASE_URL=http://localhost:8000/
|
||||
BASE_URL=http://127.0.0.1:8000/
|
||||
# Optional: additional scopes tokens must include (comma-separated)
|
||||
# SCALEKIT_REQUIRED_SCOPES=read,write
|
||||
```
|
||||
|
|
@ -38,7 +38,7 @@ Start the server:
|
|||
uv run python server.py
|
||||
```
|
||||
|
||||
The server will start on `http://localhost:8000/mcp` with Scalekit OAuth authentication enabled.
|
||||
The server will start on `http://127.0.0.1:8000/mcp` with Scalekit OAuth authentication enabled.
|
||||
|
||||
Test with client:
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Required environment variables:
|
|||
|
||||
Optional:
|
||||
- SCALEKIT_REQUIRED_SCOPES: Comma-separated scopes tokens must include
|
||||
- BASE_URL: Public URL where the FastMCP server is exposed (defaults to `http://localhost:8000/`)
|
||||
- BASE_URL: Public URL where the FastMCP server is exposed (defaults to `http://127.0.0.1:8000/`)
|
||||
|
||||
To run:
|
||||
python server.py
|
||||
|
|
@ -30,7 +30,7 @@ auth = ScalekitProvider(
|
|||
environment_url=os.getenv("SCALEKIT_ENVIRONMENT_URL")
|
||||
or "https://your-env.scalekit.com",
|
||||
resource_id=os.getenv("SCALEKIT_RESOURCE_ID") or "",
|
||||
base_url=os.getenv("BASE_URL", "http://localhost:8000/"),
|
||||
base_url=os.getenv("BASE_URL", "http://127.0.0.1:8000/"),
|
||||
required_scopes=required_scopes,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ auth = WorkOSProvider(
|
|||
client_id=os.getenv("WORKOS_CLIENT_ID") or "",
|
||||
client_secret=os.getenv("WORKOS_CLIENT_SECRET") or "",
|
||||
authkit_domain=os.getenv("WORKOS_AUTHKIT_DOMAIN") or "https://your-app.authkit.app",
|
||||
base_url="http://localhost:8000",
|
||||
base_url="http://127.0.0.1:8000",
|
||||
# redirect_path="/auth/callback", # Default path - change if using a different callback URL
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue