feat(auth): implement OAuth 2.0 authorization code flow and dynamic client registration
- Add OAuth 2.0 support with authorization code flow and dynamic client registration. - Introduce new handlers for OAuth metadata, client registration, authorization, and token issuance. - Enhance authentication middleware to support OAuth client credentials. - Create in-memory stores for authorization codes and tokens. - Update configuration to include OAuth client details. - Ensure validation checks for OAuth clients in the configuration.
This commit is contained in:
@@ -50,10 +50,24 @@ func Run(ctx context.Context, configPath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
keyring, err := auth.NewKeyring(cfg.Auth.Keys)
|
||||
if err != nil {
|
||||
return err
|
||||
var keyring *auth.Keyring
|
||||
var oauthRegistry *auth.OAuthRegistry
|
||||
var tokenStore *auth.TokenStore
|
||||
if len(cfg.Auth.Keys) > 0 {
|
||||
keyring, err = auth.NewKeyring(cfg.Auth.Keys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(cfg.Auth.OAuth.Clients) > 0 {
|
||||
oauthRegistry, err = auth.NewOAuthRegistry(cfg.Auth.OAuth.Clients)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tokenStore = auth.NewTokenStore(0)
|
||||
}
|
||||
authCodes := auth.NewAuthCodeStore()
|
||||
dynClients := auth.NewDynamicClientStore()
|
||||
activeProjects := session.NewActiveProjects()
|
||||
|
||||
logger.Info("database connection verified",
|
||||
@@ -62,7 +76,7 @@ func Run(ctx context.Context, configPath string) error {
|
||||
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port),
|
||||
Handler: routes(logger, cfg, db, provider, keyring, activeProjects),
|
||||
Handler: routes(logger, cfg, db, provider, keyring, oauthRegistry, tokenStore, authCodes, dynClients, activeProjects),
|
||||
ReadTimeout: cfg.Server.ReadTimeout,
|
||||
WriteTimeout: cfg.Server.WriteTimeout,
|
||||
IdleTimeout: cfg.Server.IdleTimeout,
|
||||
@@ -92,7 +106,7 @@ func Run(ctx context.Context, configPath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
func routes(logger *slog.Logger, cfg *config.Config, db *store.DB, provider ai.Provider, keyring *auth.Keyring, activeProjects *session.ActiveProjects) http.Handler {
|
||||
func routes(logger *slog.Logger, cfg *config.Config, db *store.DB, provider ai.Provider, keyring *auth.Keyring, oauthRegistry *auth.OAuthRegistry, tokenStore *auth.TokenStore, authCodes *auth.AuthCodeStore, dynClients *auth.DynamicClientStore, activeProjects *session.ActiveProjects) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
toolSet := mcpserver.ToolSet{
|
||||
@@ -112,7 +126,13 @@ func routes(logger *slog.Logger, cfg *config.Config, db *store.DB, provider ai.P
|
||||
}
|
||||
|
||||
mcpHandler := mcpserver.New(cfg.MCP, toolSet)
|
||||
mux.Handle(cfg.MCP.Path, auth.Middleware(cfg.Auth, keyring, logger)(mcpHandler))
|
||||
mux.Handle(cfg.MCP.Path, auth.Middleware(cfg.Auth, keyring, oauthRegistry, tokenStore, logger)(mcpHandler))
|
||||
if oauthRegistry != nil && tokenStore != nil {
|
||||
mux.HandleFunc("/.well-known/oauth-authorization-server", oauthMetadataHandler())
|
||||
mux.HandleFunc("/oauth/register", oauthRegisterHandler(dynClients, logger))
|
||||
mux.HandleFunc("/oauth/authorize", oauthAuthorizeHandler(dynClients, authCodes, logger))
|
||||
mux.HandleFunc("/oauth/token", oauthTokenHandler(oauthRegistry, tokenStore, authCodes, logger))
|
||||
}
|
||||
mux.HandleFunc("/favicon.ico", serveFavicon)
|
||||
mux.HandleFunc("/llm", serveLLMInstructions)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user