From 6a592430898385524750545409dbee718cb10b2e Mon Sep 17 00:00:00 2001 From: Takanori Hirano Date: Sun, 17 Aug 2025 16:57:38 +0000 Subject: [PATCH 1/3] feat!: replace global secret parameter with auto-generated secret - Remove GLOBAL_SECRET environment variable and command line flag - Add LoadOrGenerateSecret function to automatically generate and persist secrets - Update documentation to remove global secret references - Add developer guidelines for conventional commits BREAKING CHANGE: GLOBAL_SECRET environment variable and --global-secret flag are no longer supported. Secrets are now automatically generated and persisted. --- README.md | 52 +++++++++++++++++++++++++++++++++++++++---- main.go | 3 --- pkg/mcp-proxy/main.go | 9 ++++---- pkg/utils/keys.go | 18 +++++++++++++++ 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a3d4309..d9bc752 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ If this project saves you time, please give it a star — it really helps visibi docker run --rm -p 80:80 --net=host \ -e EXTERNAL_URL=http://localhost \ -e PROXY_URL=http://localhost:8080 \ - -e GLOBAL_SECRET=$(openssl rand -hex 32) \ -e PASSWORD=changeme \ -v ./data:/data \ ghcr.io/sigbit/mcp-auth-proxy:latest @@ -53,7 +52,6 @@ For a simpler approach to publish local MCP servers over OAuth, consider [MCP Wa | `DATA_PATH` | No | Data directory path | `./data` | | `EXTERNAL_URL` | No | External URL for OAuth callbacks | `http://localhost` | | `PROXY_URL` | No | Target MCP server URL | `http://localhost:8080` | -| `GLOBAL_SECRET` | No | Global secret for session encryption | `supersecret` | | `GOOGLE_CLIENT_ID` | No | Google OAuth client ID | - | | `GOOGLE_CLIENT_SECRET` | No | Google OAuth client secret | - | | `GOOGLE_ALLOWED_USERS` | No | Comma-separated list of allowed Google emails | - | @@ -87,7 +85,6 @@ Download the latest binary from [releases](https://github.com/sigbit/mcp-auth-pr ./mcp-auth-proxy \ --external-url "http://localhost:8081" \ --proxy-url "http://localhost:8080" \ - --global-secret "$(openssl rand -hex 32)" \ --google-client-id "your-google-client-id" \ --google-client-secret "your-google-client-secret" \ --google-allowed-users "user1@example.com,user2@example.com" \ @@ -103,7 +100,6 @@ Download the latest binary from [releases](https://github.com/sigbit/mcp-auth-pr docker run --rm -p 8081:8081 --net=host \ -e EXTERNAL_URL=http://localhost:8081 \ -e PROXY_URL=http://localhost:8080 \ - -e GLOBAL_SECRET=$(openssl rand -hex 32) \ -e GOOGLE_CLIENT_ID="your-google-client-id" \ -e GOOGLE_CLIENT_SECRET="your-google-client-secret" \ -e GOOGLE_ALLOWED_USERS="user1@example.com,user2@example.com" \ @@ -114,3 +110,51 @@ docker run --rm -p 8081:8081 --net=host \ -v ./data:/data \ ghcr.io/sigbit/mcp-auth-proxy:latest ``` + +## 👨‍💻 For Developers + +### Commit Message Guidelines + +This project follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification for commit messages. This helps with automated versioning, changelog generation, and makes the commit history more readable. + +#### Format + +``` +[optional scope]: + +[optional body] + +[optional footer(s)] +``` + +#### Types + +- **feat**: A new feature +- **fix**: A bug fix +- **docs**: Documentation only changes +- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) +- **refactor**: A code change that neither fixes a bug nor adds a feature +- **perf**: A code change that improves performance +- **test**: Adding missing tests or correcting existing tests +- **build**: Changes that affect the build system or external dependencies +- **ci**: Changes to our CI configuration files and scripts +- **chore**: Other changes that don't modify src or test files +- **revert**: Reverts a previous commit + +#### Examples + +``` +feat: add GitHub OAuth provider support +fix: resolve token expiration handling +docs: update OAuth setup instructions +refactor: simplify authentication middleware +ci: add automated release workflow +``` + +#### Breaking Changes + +Breaking changes should be indicated by a `!` after the type/scope: + +``` +feat!: change authentication API to support multiple providers +``` diff --git a/main.go b/main.go index 4f00317..b53a4d0 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,6 @@ func main() { var dataPath string var externalURL string var proxyURL string - var globalSecret string var googleClientID string var googleClientSecret string var googleAllowedUsers string @@ -72,7 +71,6 @@ func main() { dataPath, externalURL, proxyURL, - globalSecret, googleClientID, googleClientSecret, googleAllowedUsersList, @@ -95,7 +93,6 @@ func main() { rootCmd.Flags().StringVarP(&dataPath, "data", "d", getEnvWithDefault("DATA_PATH", "./data"), "Path to the data directory") rootCmd.Flags().StringVarP(&externalURL, "external-url", "e", getEnvWithDefault("EXTERNAL_URL", "http://localhost"), "External URL for the proxy") rootCmd.Flags().StringVarP(&proxyURL, "proxy-url", "p", getEnvWithDefault("PROXY_URL", "http://localhost:8080"), "Proxy URL for the proxy") - rootCmd.Flags().StringVarP(&globalSecret, "global-secret", "s", getEnvWithDefault("GLOBAL_SECRET", "supersecret"), "Global secret for the proxy") // Google OAuth configuration rootCmd.Flags().StringVar(&googleClientID, "google-client-id", getEnvWithDefault("GOOGLE_CLIENT_ID", ""), "Google OAuth client ID") diff --git a/pkg/mcp-proxy/main.go b/pkg/mcp-proxy/main.go index 792ff1d..f34a42e 100644 --- a/pkg/mcp-proxy/main.go +++ b/pkg/mcp-proxy/main.go @@ -2,7 +2,6 @@ package mcpproxy import ( "context" - "crypto/sha256" "errors" "fmt" "net/http" @@ -37,7 +36,6 @@ func Run( dataPath string, externalURL string, proxyURL string, - globalSecret string, googleClientID string, googleClientSecret string, googleAllowedUsers []string, @@ -54,8 +52,11 @@ func Run( if parsedExternalURL.Path != "" { return fmt.Errorf("external URL must not have a path, got: %s", parsedExternalURL.Path) } - sha256Hash := sha256.Sum256([]byte(globalSecret)) - secret := sha256Hash[:] + + secret, err := utils.LoadOrGenerateSecret(path.Join(dataPath, "secret")) + if err != nil { + return fmt.Errorf("failed to load or generate secret: %w", err) + } var config zap.Config if os.Getenv("MODE") == "debug" { diff --git a/pkg/utils/keys.go b/pkg/utils/keys.go index 436b7b4..f57b7f0 100644 --- a/pkg/utils/keys.go +++ b/pkg/utils/keys.go @@ -9,6 +9,24 @@ import ( "os" ) +func LoadOrGenerateSecret(secretPath string) ([]byte, error) { + _, err := os.Stat(secretPath) + if os.IsNotExist(err) { + secret := make([]byte, 32) + if _, err := rand.Read(secret); err != nil { + return nil, fmt.Errorf("failed to generate secret: %w", err) + } + if err := os.WriteFile(secretPath, secret, 0600); err != nil { + return nil, fmt.Errorf("failed to save secret: %w", err) + } + return secret, nil + } + if err != nil { + return nil, fmt.Errorf("failed to stat secret file: %w", err) + } + return os.ReadFile(secretPath) +} + func LoadOrGeneratePrivateKey(keyPath string) (*rsa.PrivateKey, error) { _, err := os.Stat(keyPath) if os.IsNotExist(err) { From 98f82cb663bc26e08d86c38f4804b7e44fc630b7 Mon Sep 17 00:00:00 2001 From: Takanori Hirano Date: Mon, 18 Aug 2025 01:59:38 +0900 Subject: [PATCH 2/3] Update pkg/utils/keys.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pkg/utils/keys.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/utils/keys.go b/pkg/utils/keys.go index f57b7f0..6841b2f 100644 --- a/pkg/utils/keys.go +++ b/pkg/utils/keys.go @@ -24,7 +24,11 @@ func LoadOrGenerateSecret(secretPath string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("failed to stat secret file: %w", err) } - return os.ReadFile(secretPath) + secret, err := os.ReadFile(secretPath) + if err != nil { + return nil, fmt.Errorf("failed to read secret file: %w", err) + } + return secret, nil } func LoadOrGeneratePrivateKey(keyPath string) (*rsa.PrivateKey, error) { From 79b5a43cc13358f965bc1a4afac42bebaf9e32d0 Mon Sep 17 00:00:00 2001 From: Takanori Hirano Date: Sun, 17 Aug 2025 17:00:35 +0000 Subject: [PATCH 3/3] refactor: extract secret size to named constant Replace magic number 32 with SecretSize constant for better maintainability. --- pkg/utils/keys.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/utils/keys.go b/pkg/utils/keys.go index 6841b2f..2d47e48 100644 --- a/pkg/utils/keys.go +++ b/pkg/utils/keys.go @@ -9,10 +9,12 @@ import ( "os" ) +const SecretSize = 32 + func LoadOrGenerateSecret(secretPath string) ([]byte, error) { _, err := os.Stat(secretPath) if os.IsNotExist(err) { - secret := make([]byte, 32) + secret := make([]byte, SecretSize) if _, err := rand.Read(secret); err != nil { return nil, fmt.Errorf("failed to generate secret: %w", err) }