OAuth 2.1授权库

用于Go语言的OAuth 2.1授权服务器库,支持PKCE、动态客户端注册和API密钥认证。

  • by alexjbarnes
  • Go
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 alexjbarnes/mcp-auth

使用说明

mcp身份验证

面向Go的OAuth 2.1授权服务器库,专为MCP(模型上下文协议)服务器设计。

提供一个完整的OAuth 2.1实现,包括PKCE、动态客户端注册(RFC 7591)、受保护的资源元数据(RFC 9728)和API密钥身份验证。将处理程序连接到HTTP多路复用器中,并带来自己的存储后端。

安装

go get github.com/alexjbarnes/mcp-auth

快速开始

package main

import (
	"net/http"

	mcpauth "github.com/alexjbarnes/mcp-auth"
)

func main() {
	srv := mcpauth.New(mcpauth.Config{
		ServerURL: "https://example.com",
		Users:     mcpauth.NewMapAuthenticator(map[string]string{
			"alice": "password123",
		}),
		GrantTypes: []string{"authorization_code", "refresh_token", "client_credentials"},
	})
	defer srv.Stop()

	mux := http.NewServeMux()

	// Register all OAuth endpoints.
	srv.Register(mux)

	// Protect your application routes with the middleware.
	mux.Handle("/mcp", srv.Middleware()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		userID := mcpauth.RequestUserID(r.Context())
		w.Write([]byte("hello " + userID))
	})))

	http.ListenAndServe(":8080", mux)
}

端点

srv.Register(mux) 导线:

方法 路径 描述
得到 /.well-known/oauth-protected-resource 受保护的资源元数据(RFC 9728)
得到 /.well-known/oauth-authorization-server 授权服务器元数据(RFC 8414)
职位 /oauth/register 动态客户端注册(RFC 7591)
得到 /oauth/authorize 授权码流(显示登录页面)
职位 /oauth/authorize 授权码流(处理登录)
职位 /oauth/token 代币交换和刷新

API密钥

在没有OAuth流的情况下注册服务到服务身份验证的API密钥。

// With a prefix to distinguish from OAuth tokens.
srv := mcpauth.New(mcpauth.Config{
	ServerURL:    "https://example.com",
	APIKeyPrefix: "sk_",
})
srv.RegisterAPIKey("sk_live_abc123", "service-account")

// Without a prefix. Tokens are speculatively checked as API keys
// and fall through to OAuth validation if not found.
srv := mcpauth.New(mcpauth.Config{
	ServerURL: "https://example.com",
})
srv.RegisterAPIKey("abc123", "service-account")

// Register by pre-computed hash when you don't have the raw key.
srv.RegisterAPIKeyByHash(mcpauth.HashSecret("abc123"), "service-account")

预配置的客户端

注册绕过动态注册的服务器拥有的OAuth客户端。

err := srv.RegisterPreConfiguredClient(&mcpauth.OAuthClient{
	ClientID:   "my-service",
	SecretHash: mcpauth.HashSecret("client-secret"),
	GrantTypes: []string{"client_credentials"},
})
if err != nil {
	// Grant type not supported by server configuration.
	log.Fatal(err)
}

存储

默认情况下,所有内容都在内存中。为了实现持久存储,请实施 Persistence 接口并通过传递 Config.Persist.

type Persistence interface {
	SaveOAuthToken(token OAuthToken) error
	DeleteOAuthToken(tokenHash string) error
	AllOAuthTokens() ([]OAuthToken, error)

	SaveOAuthClient(client OAuthClient) error
	DeleteOAuthClient(clientID string) error
	AllOAuthClients() ([]OAuthClient, error)

	SaveAPIKey(hash string, key APIKey) error
	DeleteAPIKey(hash string) error
	AllAPIKeys() (map[string]APIKey, error)
}

原始秘密(令牌、刷新令牌)永远不会传递给持久层。只存储哈希值。

用户认证

实施 UserAuthenticator 用于自定义凭证验证(LDAP、数据库等)。

type UserAuthenticator interface {
	ValidateCredentials(ctx context.Context, username, password string) (userID string, err error)
}

MapAuthenticator 是一个由用户名/密码映射支持的内置实现。密码在构建时被散列,不会被保留。

users := mcpauth.NewMapAuthenticator(map[string]string{
	"alice": "password123",
	"bob":   "hunter2",
})

可选实施 UserAccountChecker 在同一类型上启用中间件中的每个请求帐户验证(禁用用户而不撤销令牌)。

上下文助手

在中间件对请求进行身份验证后,从上下文中提取身份:

userID   := mcpauth.RequestUserID(r.Context())
clientID := mcpauth.RequestClientID(r.Context())
ip       := mcpauth.RequestRemoteIP(r.Context())

WithUserID 将用户ID注入上下文进行测试:

ctx := mcpauth.WithUserID(context.Background(), "test-user")

许可证

Apache 2.0