feat(auth): add additional OAuth endpoints and improve client ID handling

This commit is contained in:
2026-03-26 22:30:23 +02:00
parent 56c84df342
commit 1dde7f233d
3 changed files with 13 additions and 5 deletions

View File

@@ -129,7 +129,9 @@ func routes(logger *slog.Logger, cfg *config.Config, db *store.DB, provider ai.P
mux.Handle(cfg.MCP.Path, auth.Middleware(cfg.Auth, keyring, oauthRegistry, tokenStore, logger)(mcpHandler)) mux.Handle(cfg.MCP.Path, auth.Middleware(cfg.Auth, keyring, oauthRegistry, tokenStore, logger)(mcpHandler))
if oauthRegistry != nil && tokenStore != nil { if oauthRegistry != nil && tokenStore != nil {
mux.HandleFunc("/.well-known/oauth-authorization-server", oauthMetadataHandler()) mux.HandleFunc("/.well-known/oauth-authorization-server", oauthMetadataHandler())
mux.HandleFunc("/oauth-authorization-server", oauthMetadataHandler())
mux.HandleFunc("/oauth/register", oauthRegisterHandler(dynClients, logger)) mux.HandleFunc("/oauth/register", oauthRegisterHandler(dynClients, logger))
mux.HandleFunc("/authorize", oauthAuthorizeHandler(dynClients, authCodes, logger))
mux.HandleFunc("/oauth/authorize", oauthAuthorizeHandler(dynClients, authCodes, logger)) mux.HandleFunc("/oauth/authorize", oauthAuthorizeHandler(dynClients, authCodes, logger))
mux.HandleFunc("/oauth/token", oauthTokenHandler(oauthRegistry, tokenStore, authCodes, logger)) mux.HandleFunc("/oauth/token", oauthTokenHandler(oauthRegistry, tokenStore, authCodes, logger))
} }

View File

@@ -66,7 +66,7 @@ func oauthMetadataHandler() http.HandlerFunc {
base := serverBaseURL(r) base := serverBaseURL(r)
meta := oauthServerMetadata{ meta := oauthServerMetadata{
Issuer: base, Issuer: base,
AuthorizationEndpoint: base + "/oauth/authorize", AuthorizationEndpoint: base + "/authorize",
TokenEndpoint: base + "/oauth/token", TokenEndpoint: base + "/oauth/token",
RegistrationEndpoint: base + "/oauth/register", RegistrationEndpoint: base + "/oauth/register",
ScopesSupported: []string{"mcp"}, ScopesSupported: []string{"mcp"},

View File

@@ -2,7 +2,8 @@ package auth
import ( import (
"crypto/rand" "crypto/rand"
"encoding/hex" "fmt"
"strings"
"sync" "sync"
"time" "time"
) )
@@ -42,21 +43,26 @@ func (s *DynamicClientStore) Register(name string, redirectURIs []string) (Dynam
return DynamicClient{}, err return DynamicClient{}, err
} }
client := DynamicClient{ client := DynamicClient{
ClientID: hex.EncodeToString(b), ClientID: fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]),
ClientName: name, ClientName: name,
RedirectURIs: append([]string(nil), redirectURIs...), RedirectURIs: append([]string(nil), redirectURIs...),
CreatedAt: time.Now(), CreatedAt: time.Now(),
} }
s.mu.Lock() s.mu.Lock()
s.clients[client.ClientID] = client s.clients[normalizeClientID(client.ClientID)] = client
s.mu.Unlock() s.mu.Unlock()
return client, nil return client, nil
} }
// Lookup returns the client for the given client_id. // Lookup returns the client for the given client_id.
// Accepts UUIDs with or without dashes.
func (s *DynamicClientStore) Lookup(clientID string) (DynamicClient, bool) { func (s *DynamicClientStore) Lookup(clientID string) (DynamicClient, bool) {
s.mu.RLock() s.mu.RLock()
client, ok := s.clients[clientID] client, ok := s.clients[normalizeClientID(clientID)]
s.mu.RUnlock() s.mu.RUnlock()
return client, ok return client, ok
} }
func normalizeClientID(id string) string {
return strings.ReplaceAll(id, "-", "")
}