OAuth 2.1 authorization server for remote MCP servers.
forge-oauth is a standalone Go library that implements an OAuth 2.1 authorization server for use with remote Model Context Protocol servers. ChatGPT Plus and Claude.ai require OAuth 2.1 to connect to remote MCP servers; forge-oauth provides the server-side implementation.
- OAuth 2.1 (draft-15): PKCE mandatory, no implicit flow, no ROPC
- RFC 8414: Authorization Server Metadata
- RFC 9728: Protected Resource Metadata (via
forge-cms.dev/forge-mcp) - CIMD: Client ID Metadata Documents — stateless client validation
- Stateless client validation via CIMD (no client registration database)
- PKCE S256 — mandatory for all authorization requests
- Refresh tokens via
offline_accessscope (required for ChatGPT) - HTML authorization form — user pastes their existing Forge bearer token
- SQLite storage out of the box (
modernc.org/sqlite— no CGO) slog-based structured logging
go get forge-cms.dev/forge-oauth
Requires Go 1.26.3+.
import (
"log"
"net/http"
"forge-cms.dev/forge"
forgeoauth "forge-cms.dev/forge-oauth"
forgemcp "forge-cms.dev/forge-mcp"
)
func main() {
app := forge.New(forge.Config{...})
store, err := forgeoauth.NewSQLiteStore("./forge-oauth.db")
if err != nil {
log.Fatal(err)
}
oauthSrv := forgeoauth.New(forgeoauth.Config{
Issuer: "https://cms.example.com",
VerifyBearer: func(token string) bool {
// Validate Forge bearer token using forge.VerifyTokenString (v1.25.0+).
_, ok := forge.VerifyTokenString(token, app.Secret(), app.TokenStore())
return ok
},
}, store)
mcpSrv := forgemcp.New(app, forgemcp.WithOAuth(oauthSrv))
http.ListenAndServe(":8080", mcpSrv.Handler())
}| Method | Path | Description |
|---|---|---|
GET |
/.well-known/oauth-authorization-server |
RFC 8414 metadata |
GET |
/oauth/authorize |
Authorization form |
POST |
/oauth/authorize |
Form submission |
POST |
/oauth/token |
Code exchange and token refresh |
To test end-to-end with ChatGPT Plus:
- Install ngrok:
winget install ngrok.ngrok - Configure:
ngrok config add-authtoken <your-token> - Start your Forge + MCP server locally on port 8080
- Run
ngrok http 8080— note the HTTPS URL (e.g.https://abc123.ngrok-free.app) - Set
Issuer: "https://abc123.ngrok-free.app"inforgeoauth.Config - Restart the server with the ngrok URL
- In ChatGPT Plus: Settings → Connected Apps → Add → paste the ngrok HTTPS URL
- ChatGPT triggers the OAuth flow → browser opens the authorization form
- Paste your Forge bearer token → click Approve
- ChatGPT receives an access token and can call MCP tools (e.g.
list_posts)
Three SQLite tables are created automatically by NewSQLiteStore:
| Table | Purpose |
|---|---|
forge_oauth_codes |
Short-lived authorization codes (5 min default) |
forge_oauth_tokens |
Access tokens (1 hour default) |
forge_oauth_refresh_tokens |
Refresh tokens (no expiry in v1) |
MIT — see LICENSE.
Part of the Forge CMS ecosystem.