From 4a5cf4e1cc2c5b8ab5ee4cfa0c94080d6493530c Mon Sep 17 00:00:00 2001 From: Pavindu Lakshan Date: Sun, 27 Apr 2025 17:23:13 +0530 Subject: [PATCH 01/13] Update README.md --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 71b4b60..6be3ece 100644 --- a/README.md +++ b/README.md @@ -47,15 +47,7 @@ Open MCP Auth Proxy sits between MCP clients and your MCP server to: ### Basic Usage -1. The repository comes with a default `config.yaml` file that contains the basic configuration: - -```yaml -listen_port: 8080 -base_url: "http://localhost:8000" # Your MCP server URL -paths: - sse: "/sse" - messages: "/messages/" -``` +1. Download the latest release from [Github releases](https://github.com/wso2/open-mcp-auth-proxy/releases/latest). 2. Start the proxy in demo mode (uses pre-configured authentication with Asgardeo sandbox): @@ -63,6 +55,16 @@ paths: ./openmcpauthproxy --demo ``` +> The repository comes with a default `config.yaml` file that contains the basic configuration: +> +> ```yaml +> listen_port: 8080 +> base_url: "http://localhost:8000" # Your MCP server URL +> paths: +> sse: "/sse" +> messages: "/messages/" +> ``` + 3. Connect using an MCP client like [MCP Inspector](https://github.com/shashimalcse/inspector)(This is a temporary fork with fixes for authentication [issues](https://github.com/modelcontextprotocol/typescript-sdk/issues/257) in the original implementation) ## Connect an Identity Provider From 0bbc20ca5a1c4f804fb901071109f4a426d8b8de Mon Sep 17 00:00:00 2001 From: Pavindu Lakshan Date: Sat, 3 May 2025 01:06:41 +0530 Subject: [PATCH 02/13] Remove unnecessary fields from PR template --- pull_request_template.md | 51 ++++------------------------------------ 1 file changed, 5 insertions(+), 46 deletions(-) diff --git a/pull_request_template.md b/pull_request_template.md index 9b32185..c401a06 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,52 +1,11 @@ ## Purpose -> Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc. + -## Goals -> Describe the solutions that this feature/fix will introduce to resolve the problems described above - -## Approach -> Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here. - -## User stories -> Summary of user stories addressed by this change> - -## Release note -> Brief description of the new feature or bug fix as it will appear in the release notes - -## Documentation -> Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact - -## Training -> Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable - -## Certification -> Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why. - -## Marketing -> Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable - -## Automation tests - - Unit tests - > Code coverage information - - Integration tests - > Details about the test cases and coverage - -## Security checks - - Followed secure coding standards in http://wso2.com/technical-reports/wso2-secure-engineering-guidelines? yes/no - - Ran FindSecurityBugs plugin and verified report? yes/no - - Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets? yes/no - -## Samples -> Provide high-level details about the samples related to this feature +## Related Issues + ## Related PRs -> List any other related PRs + ## Migrations (if applicable) -> Describe migration steps and platforms on which migration has been tested - -## Test environment -> List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested - -## Learning -> Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem. \ No newline at end of file + From 68015ae8fc9897526cdc01c1c49afc0d7770c925 Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Sun, 18 May 2025 14:19:36 +0530 Subject: [PATCH 03/13] Handle spawning subprocess within windows --- .gitignore | 4 + internal/config/config.go | 13 ++- internal/subprocess/manager.go | 152 ++++++++++++++++--------- internal/subprocess/manager_unix.go | 23 ++++ internal/subprocess/manager_windows.go | 27 +++++ 5 files changed, 167 insertions(+), 52 deletions(-) create mode 100644 internal/subprocess/manager_unix.go create mode 100644 internal/subprocess/manager_windows.go diff --git a/.gitignore b/.gitignore index d200b58..f2bcda1 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,7 @@ coverage.html # IDE files .vscode + +# node modules +node_modules +openmcpauthproxy diff --git a/internal/config/config.go b/internal/config/config.go index fc6743c..c50d9ed 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,6 +3,8 @@ package config import ( "fmt" "os" + "runtime" + "strings" "gopkg.in/yaml.v2" ) @@ -145,7 +147,16 @@ func (c *Config) BuildExecCommand() string { return "" } - // Construct the full command + + if runtime.GOOS == "windows" { + // For Windows, we need to properly escape the inner command + escapedCommand := strings.ReplaceAll(c.Stdio.UserCommand, `"`, `\"`) + return fmt.Sprintf( + `npx -y supergateway --stdio "%s" --port %d --baseUrl %s --ssePath %s --messagePath %s`, + escapedCommand, c.Port, c.BaseURL, c.Paths.SSE, c.Paths.Messages, + ) + } + return fmt.Sprintf( `npx -y supergateway --stdio "%s" --port %d --baseUrl %s --ssePath %s --messagePath %s`, c.Stdio.UserCommand, c.Port, c.BaseURL, c.Paths.SSE, c.Paths.Messages, diff --git a/internal/subprocess/manager.go b/internal/subprocess/manager.go index fa64337..6230fe0 100644 --- a/internal/subprocess/manager.go +++ b/internal/subprocess/manager.go @@ -8,6 +8,7 @@ import ( "syscall" "time" "strings" + "runtime" "github.com/wso2/open-mcp-auth-proxy/internal/config" "github.com/wso2/open-mcp-auth-proxy/internal/logging" @@ -40,7 +41,12 @@ func EnsureDependenciesAvailable(command string) error { // Try to install npx using npm logger.Info("npx not found, attempting to install...") - cmd := exec.Command("npm", "install", "-g", "npx") + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + cmd = exec.Command("npm.cmd", "install", "-g", "npx") + } else { + cmd = exec.Command("npm", "install", "-g", "npx") + } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -88,8 +94,13 @@ func (m *Manager) Start(cfg *config.Config) error { logger.Info("Starting subprocess with command: %s", execCommand) - // Use the shell to execute the command - cmd := exec.Command("sh", "-c", execCommand) + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + // Use PowerShell on Windows for better quote handling + cmd = exec.Command("powershell", "-Command", execCommand) + } else { + cmd = exec.Command("sh", "-c", execCommand) + } // Set working directory if specified if cfg.Stdio.WorkDir != "" { @@ -105,8 +116,8 @@ func (m *Manager) Start(cfg *config.Config) error { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - // Set the process group for proper termination - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + // Set platform-specific process attributes + setProcAttr(cmd) // Start the process if err := cmd.Start(); err != nil { @@ -117,11 +128,13 @@ func (m *Manager) Start(cfg *config.Config) error { m.cmd = cmd logger.Info("Subprocess started with PID: %d", m.process.Pid) - // Get and store the process group ID - pgid, err := syscall.Getpgid(m.process.Pid) + // Get and store the process group ID (Unix) or PID (Windows) + pgid, err := getProcessGroup(m.process.Pid) if err == nil { m.processGroup = pgid - logger.Debug("Process group ID: %d", m.processGroup) + if runtime.GOOS != "windows" { + logger.Debug("Process group ID: %d", m.processGroup) + } } else { logger.Warn("Failed to get process group ID: %v", err) m.processGroup = m.process.Pid @@ -169,48 +182,73 @@ func (m *Manager) Shutdown() { go func() { defer close(terminateComplete) - // Try graceful termination first with SIGTERM + // Try graceful termination first terminatedGracefully := false - // Try to terminate the process group first - if processGroupToTerminate != 0 { - err := syscall.Kill(-processGroupToTerminate, syscall.SIGTERM) - if err != nil { - logger.Warn("Failed to send SIGTERM to process group: %v", err) + if runtime.GOOS == "windows" { + // Windows: Try to terminate the process + m.mutex.Lock() + if m.process != nil { + err := m.process.Kill() + if err != nil { + logger.Warn("Failed to terminate process: %v", err) + } + } + m.mutex.Unlock() - // Fallback to terminating just the process + // Wait a bit to see if it terminates + for i := 0; i < 10; i++ { + time.Sleep(200 * time.Millisecond) + m.mutex.Lock() + if m.process == nil { + terminatedGracefully = true + m.mutex.Unlock() + break + } + m.mutex.Unlock() + } + } else { + // Unix: Use SIGTERM followed by SIGKILL if necessary + // Try to terminate the process group first + if processGroupToTerminate != 0 { + err := killProcessGroup(processGroupToTerminate, syscall.SIGTERM) + if err != nil { + logger.Warn("Failed to send SIGTERM to process group: %v", err) + + // Fallback to terminating just the process + m.mutex.Lock() + if m.process != nil { + err = m.process.Signal(syscall.SIGTERM) + if err != nil { + logger.Warn("Failed to send SIGTERM to process: %v", err) + } + } + m.mutex.Unlock() + } + } else { + // Try to terminate just the process m.mutex.Lock() if m.process != nil { - err = m.process.Signal(syscall.SIGTERM) + err := m.process.Signal(syscall.SIGTERM) if err != nil { logger.Warn("Failed to send SIGTERM to process: %v", err) } } m.mutex.Unlock() } - } else { - // Try to terminate just the process - m.mutex.Lock() - if m.process != nil { - err := m.process.Signal(syscall.SIGTERM) - if err != nil { - logger.Warn("Failed to send SIGTERM to process: %v", err) + + // Wait for the process to exit gracefully + for i := 0; i < 10; i++ { + time.Sleep(200 * time.Millisecond) + + m.mutex.Lock() + if m.process == nil { + terminatedGracefully = true + m.mutex.Unlock() + break } - } - m.mutex.Unlock() - } - - // Wait for the process to exit gracefully - for i := 0; i < 10; i++ { - time.Sleep(200 * time.Millisecond) - - m.mutex.Lock() - if m.process == nil { - terminatedGracefully = true m.mutex.Unlock() - break } - m.mutex.Unlock() } if terminatedGracefully { @@ -221,12 +259,33 @@ func (m *Manager) Shutdown() { // If the process didn't exit gracefully, force kill logger.Warn("Subprocess didn't exit gracefully, forcing termination...") - // Try to kill the process group first - if processGroupToTerminate != 0 { - if err := syscall.Kill(-processGroupToTerminate, syscall.SIGKILL); err != nil { - logger.Warn("Failed to send SIGKILL to process group: %v", err) + if runtime.GOOS == "windows" { + // On Windows, Kill() is already forceful + m.mutex.Lock() + if m.process != nil { + if err := m.process.Kill(); err != nil { + logger.Error("Failed to kill process: %v", err) + } + } + m.mutex.Unlock() + } else { + // Unix: Try SIGKILL + // Try to kill the process group first + if processGroupToTerminate != 0 { + if err := killProcessGroup(processGroupToTerminate, syscall.SIGKILL); err != nil { + logger.Warn("Failed to send SIGKILL to process group: %v", err) - // Fallback to killing just the process + // Fallback to killing just the process + m.mutex.Lock() + if m.process != nil { + if err := m.process.Kill(); err != nil { + logger.Error("Failed to kill process: %v", err) + } + } + m.mutex.Unlock() + } + } else { + // Try to kill just the process m.mutex.Lock() if m.process != nil { if err := m.process.Kill(); err != nil { @@ -235,15 +294,6 @@ func (m *Manager) Shutdown() { } m.mutex.Unlock() } - } else { - // Try to kill just the process - m.mutex.Lock() - if m.process != nil { - if err := m.process.Kill(); err != nil { - logger.Error("Failed to kill process: %v", err) - } - } - m.mutex.Unlock() } // Wait a bit more to confirm termination @@ -265,4 +315,4 @@ func (m *Manager) Shutdown() { case <-time.After(m.shutdownDelay): logger.Warn("Subprocess termination timed out") } -} +} \ No newline at end of file diff --git a/internal/subprocess/manager_unix.go b/internal/subprocess/manager_unix.go new file mode 100644 index 0000000..2f3dc35 --- /dev/null +++ b/internal/subprocess/manager_unix.go @@ -0,0 +1,23 @@ +//go:build !windows + +package subprocess + +import ( + "os/exec" + "syscall" +) + +// setProcAttr sets Unix-specific process attributes +func setProcAttr(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} +} + +// getProcessGroup gets the process group ID on Unix systems +func getProcessGroup(pid int) (int, error) { + return syscall.Getpgid(pid) +} + +// killProcessGroup kills a process group on Unix systems +func killProcessGroup(pgid int, signal syscall.Signal) error { + return syscall.Kill(-pgid, signal) +} \ No newline at end of file diff --git a/internal/subprocess/manager_windows.go b/internal/subprocess/manager_windows.go new file mode 100644 index 0000000..30cb2c8 --- /dev/null +++ b/internal/subprocess/manager_windows.go @@ -0,0 +1,27 @@ +//go:build windows + +package subprocess + +import ( + "os/exec" + "syscall" +) + +// setProcAttr sets Windows-specific process attributes +func setProcAttr(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP, + } +} + +// getProcessGroup returns the PID itself on Windows (no process groups) +func getProcessGroup(pid int) (int, error) { + return pid, nil +} + +// killProcessGroup kills a process on Windows (no process groups) +func killProcessGroup(pgid int, signal syscall.Signal) error { + // On Windows, we'll use the process handle directly + // This function shouldn't be called on Windows, but we provide it for compatibility + return nil +} \ No newline at end of file From 561b8fb637511399c9cd5c2885e66ffd09c906cc Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Sun, 18 May 2025 16:11:04 +0530 Subject: [PATCH 04/13] Add eof --- internal/subprocess/manager.go | 76 +++++++++++++------------- internal/subprocess/manager_unix.go | 2 +- internal/subprocess/manager_windows.go | 2 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/internal/subprocess/manager.go b/internal/subprocess/manager.go index 6230fe0..902a517 100644 --- a/internal/subprocess/manager.go +++ b/internal/subprocess/manager.go @@ -4,14 +4,14 @@ import ( "fmt" "os" "os/exec" + "runtime" + "strings" "sync" "syscall" "time" - "strings" - "runtime" "github.com/wso2/open-mcp-auth-proxy/internal/config" - "github.com/wso2/open-mcp-auth-proxy/internal/logging" + logger "github.com/wso2/open-mcp-auth-proxy/internal/logging" ) // Manager handles starting and graceful shutdown of subprocesses @@ -32,39 +32,39 @@ func NewManager() *Manager { // EnsureDependenciesAvailable checks and installs required package executors func EnsureDependenciesAvailable(command string) error { - // Always ensure npx is available regardless of the command - if _, err := exec.LookPath("npx"); err != nil { - // npx is not available, check if npm is installed - if _, err := exec.LookPath("npm"); err != nil { - return fmt.Errorf("npx not found and npm not available; please install Node.js from https://nodejs.org/") - } - - // Try to install npx using npm - logger.Info("npx not found, attempting to install...") - var cmd *exec.Cmd - if runtime.GOOS == "windows" { - cmd = exec.Command("npm.cmd", "install", "-g", "npx") - } else { - cmd = exec.Command("npm", "install", "-g", "npx") - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to install npx: %w", err) - } - - logger.Info("npx installed successfully") - } - - // Check if uv is needed based on the command - if strings.Contains(command, "uv ") { - if _, err := exec.LookPath("uv"); err != nil { - return fmt.Errorf("command requires uv but it's not installed; please install it following instructions at https://github.com/astral-sh/uv") - } - } - - return nil + // Always ensure npx is available regardless of the command + if _, err := exec.LookPath("npx"); err != nil { + // npx is not available, check if npm is installed + if _, err := exec.LookPath("npm"); err != nil { + return fmt.Errorf("npx not found and npm not available; please install Node.js from https://nodejs.org/") + } + + // Try to install npx using npm + logger.Info("npx not found, attempting to install...") + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + cmd = exec.Command("npm.cmd", "install", "-g", "npx") + } else { + cmd = exec.Command("npm", "install", "-g", "npx") + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to install npx: %w", err) + } + + logger.Info("npx installed successfully") + } + + // Check if uv is needed based on the command + if strings.Contains(command, "uv ") { + if _, err := exec.LookPath("uv"); err != nil { + return fmt.Errorf("command requires uv but it's not installed; please install it following instructions at https://github.com/astral-sh/uv") + } + } + + return nil } // SetShutdownDelay sets the maximum time to wait for graceful shutdown @@ -168,7 +168,7 @@ func (m *Manager) IsRunning() bool { // Shutdown gracefully terminates the subprocess func (m *Manager) Shutdown() { m.mutex.Lock() - processToTerminate := m.process // Local copy of the process reference + processToTerminate := m.process // Local copy of the process reference processGroupToTerminate := m.processGroup m.mutex.Unlock() @@ -315,4 +315,4 @@ func (m *Manager) Shutdown() { case <-time.After(m.shutdownDelay): logger.Warn("Subprocess termination timed out") } -} \ No newline at end of file +} diff --git a/internal/subprocess/manager_unix.go b/internal/subprocess/manager_unix.go index 2f3dc35..03ae1a8 100644 --- a/internal/subprocess/manager_unix.go +++ b/internal/subprocess/manager_unix.go @@ -20,4 +20,4 @@ func getProcessGroup(pid int) (int, error) { // killProcessGroup kills a process group on Unix systems func killProcessGroup(pgid int, signal syscall.Signal) error { return syscall.Kill(-pgid, signal) -} \ No newline at end of file +} diff --git a/internal/subprocess/manager_windows.go b/internal/subprocess/manager_windows.go index 30cb2c8..a039897 100644 --- a/internal/subprocess/manager_windows.go +++ b/internal/subprocess/manager_windows.go @@ -24,4 +24,4 @@ func killProcessGroup(pgid int, signal syscall.Signal) error { // On Windows, we'll use the process handle directly // This function shouldn't be called on Windows, but we provide it for compatibility return nil -} \ No newline at end of file +} From 8bc2e6e76bc0bb6973532440c6282d4dba1928c2 Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Sun, 18 May 2025 16:30:05 +0530 Subject: [PATCH 05/13] Add windows build step to makefile --- Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b0d0926..fbf73d6 100644 --- a/Makefile +++ b/Makefile @@ -21,12 +21,12 @@ BUILD_OPTS := -v # Set test options TEST_OPTS := -v -race -.PHONY: all clean test fmt lint vet coverage help +.PHONY: all clean test fmt lint vet coverage help build-windows # Default target -all: lint test build-linux build-linux-arm build-darwin +all: lint test build-linux build-linux-arm build-darwin build-windows -build: clean test build-linux build-linux-arm build-darwin +build: clean test build-linux build-linux-arm build-darwin build-windows build-linux: mkdir -p $(BUILD_DIR)/linux @@ -46,6 +46,12 @@ build-darwin: -o $(BUILD_DIR)/darwin/openmcpauthproxy $(PROJECT_ROOT)/cmd/proxy cp config.yaml $(BUILD_DIR)/darwin +build-windows: + mkdir -p $(BUILD_DIR)/windows + GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -x -ldflags "-X main.version=$(BUILD_VERSION)" \ + -o $(BUILD_DIR)/windows/openmcpauthproxy.exe ./cmd/proxy + cp config.yaml $(BUILD_DIR)/windows + # Clean build artifacts clean: @echo "Cleaning build artifacts..." From be697b58687d025dc7e7f6df1859d29640aa2947 Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Sun, 18 May 2025 16:39:48 +0530 Subject: [PATCH 06/13] Add build from source instructions --- README.md | 111 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6be3ece..496dd70 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,108 @@ asgardeo: - [Auth0](docs/integrations/Auth0.md) - [Keycloak](docs/integrations/keycloak.md) +## Build from Source + +### Prerequisites for Building + +* Go 1.20 or higher +* Git +* Make (for Linux/macOS builds) + +### Building on Linux/macOS + +1. Clone the repository: + ```bash + git clone https://github.com/wso2/open-mcp-auth-proxy + cd open-mcp-auth-proxy + ``` + +2. Install dependencies: + ```bash + go get -v -t -d ./... + ``` + +3. Build for your platform: + ```bash + # Build for all platforms + make all + + # Or build for a specific platform + make build-linux # For Linux + make build-darwin # For macOS + make build-linux-arm # For ARM-based Linux + make build-windows # For Windows + ``` + +4. Find your build in the `build` directory: + ```bash + # For Linux + ./build/linux/openmcpauthproxy --demo + + # For macOS + ./build/darwin/openmcpauthproxy --demo + ``` + +### Building on Windows + +1. Clone the repository: + ```powershell + git clone https://github.com/wso2/open-mcp-auth-proxy + cd open-mcp-auth-proxy + ``` + +2. Install dependencies: + ```powershell + go get -v -t -d ./... + ``` + +3. Option 1: Build using Make if you have it installed: + ```powershell + make build-windows + ``` + + Option 2: Build manually without Make: + ```powershell + mkdir -p build\windows + go build -o build\windows\openmcpauthproxy.exe .\cmd\proxy + copy config.yaml build\windows\ + ``` + +4. Run the built application: + ```powershell + cd build\windows + .\openmcpauthproxy.exe --demo + ``` + +### Starting the Proxy on Windows + +1. Open Command Prompt or PowerShell +2. Navigate to the build directory: + ```powershell + cd build\windows + ``` + +3. Run the executable with your desired options: + ```powershell + # Start in demo mode (using Asgardeo sandbox) + openmcpauthproxy.exe --demo + + # Start with Asgardeo integration + openmcpauthproxy.exe --asgardeo + + # Start in stdio mode + openmcpauthproxy.exe --demo --stdio + + # Enable debug logging + openmcpauthproxy.exe --demo --debug + + # See all available options + openmcpauthproxy.exe --help + ``` + +4. The proxy will start and display messages indicating it's running +5. To stop the proxy, press `Ctrl+C` in the command window + # Advanced Configuration ### Transport Modes @@ -215,12 +317,3 @@ asgardeo: client_id: "" client_secret: "" ``` - -### Build from source - -```bash -git clone https://github.com/wso2/open-mcp-auth-proxy -cd open-mcp-auth-proxy -go get github.com/golang-jwt/jwt/v4 gopkg.in/yaml.v2 -go build -o openmcpauthproxy ./cmd/proxy -``` From 9f856c42794c11bce7dd118d89abadddd3f9ead5 Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Sun, 18 May 2025 16:44:10 +0530 Subject: [PATCH 07/13] Move build from source to the end of readme --- Makefile | 2 +- README.md | 203 +++++++++++++++++++++++++++--------------------------- 2 files changed, 102 insertions(+), 103 deletions(-) diff --git a/Makefile b/Makefile index fbf73d6..3c0c590 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ BUILD_OPTS := -v # Set test options TEST_OPTS := -v -race -.PHONY: all clean test fmt lint vet coverage help build-windows +.PHONY: all clean test fmt lint vet coverage help # Default target all: lint test build-linux build-linux-arm build-darwin build-windows diff --git a/README.md b/README.md index 496dd70..1158c7d 100644 --- a/README.md +++ b/README.md @@ -101,108 +101,6 @@ asgardeo: - [Auth0](docs/integrations/Auth0.md) - [Keycloak](docs/integrations/keycloak.md) -## Build from Source - -### Prerequisites for Building - -* Go 1.20 or higher -* Git -* Make (for Linux/macOS builds) - -### Building on Linux/macOS - -1. Clone the repository: - ```bash - git clone https://github.com/wso2/open-mcp-auth-proxy - cd open-mcp-auth-proxy - ``` - -2. Install dependencies: - ```bash - go get -v -t -d ./... - ``` - -3. Build for your platform: - ```bash - # Build for all platforms - make all - - # Or build for a specific platform - make build-linux # For Linux - make build-darwin # For macOS - make build-linux-arm # For ARM-based Linux - make build-windows # For Windows - ``` - -4. Find your build in the `build` directory: - ```bash - # For Linux - ./build/linux/openmcpauthproxy --demo - - # For macOS - ./build/darwin/openmcpauthproxy --demo - ``` - -### Building on Windows - -1. Clone the repository: - ```powershell - git clone https://github.com/wso2/open-mcp-auth-proxy - cd open-mcp-auth-proxy - ``` - -2. Install dependencies: - ```powershell - go get -v -t -d ./... - ``` - -3. Option 1: Build using Make if you have it installed: - ```powershell - make build-windows - ``` - - Option 2: Build manually without Make: - ```powershell - mkdir -p build\windows - go build -o build\windows\openmcpauthproxy.exe .\cmd\proxy - copy config.yaml build\windows\ - ``` - -4. Run the built application: - ```powershell - cd build\windows - .\openmcpauthproxy.exe --demo - ``` - -### Starting the Proxy on Windows - -1. Open Command Prompt or PowerShell -2. Navigate to the build directory: - ```powershell - cd build\windows - ``` - -3. Run the executable with your desired options: - ```powershell - # Start in demo mode (using Asgardeo sandbox) - openmcpauthproxy.exe --demo - - # Start with Asgardeo integration - openmcpauthproxy.exe --asgardeo - - # Start in stdio mode - openmcpauthproxy.exe --demo --stdio - - # Enable debug logging - openmcpauthproxy.exe --demo --debug - - # See all available options - openmcpauthproxy.exe --help - ``` - -4. The proxy will start and display messages indicating it's running -5. To stop the proxy, press `Ctrl+C` in the command window - # Advanced Configuration ### Transport Modes @@ -317,3 +215,104 @@ asgardeo: client_id: "" client_secret: "" ``` +## Build from Source + +### Prerequisites for Building + +* Go 1.20 or higher +* Git +* Make (for Linux/macOS builds) + +### Building on Linux/macOS + +1. Clone the repository: + ```bash + git clone https://github.com/wso2/open-mcp-auth-proxy + cd open-mcp-auth-proxy + ``` + +2. Install dependencies: + ```bash + go get -v -t -d ./... + ``` + +3. Build for your platform: + ```bash + # Build for all platforms + make all + + # Or build for a specific platform + make build-linux # For Linux + make build-darwin # For macOS + make build-linux-arm # For ARM-based Linux + make build-windows # For Windows + ``` + +4. Find your build in the `build` directory: + ```bash + # For Linux + ./build/linux/openmcpauthproxy --demo + + # For macOS + ./build/darwin/openmcpauthproxy --demo + ``` + +### Building on Windows + +1. Clone the repository: + ```powershell + git clone https://github.com/wso2/open-mcp-auth-proxy + cd open-mcp-auth-proxy + ``` + +2. Install dependencies: + ```powershell + go get -v -t -d ./... + ``` + +3. Option 1: Build using Make if you have it installed: + ```powershell + make build-windows + ``` + + Option 2: Build manually without Make: + ```powershell + mkdir -p build\windows + go build -o build\windows\openmcpauthproxy.exe .\cmd\proxy + copy config.yaml build\windows\ + ``` + +4. Run the built application: + ```powershell + cd build\windows + .\openmcpauthproxy.exe --demo + ``` + +### Starting the Proxy on Windows + +1. Open Command Prompt or PowerShell +2. Navigate to the build directory: + ```powershell + cd build\windows + ``` + +3. Run the executable with your desired options: + ```powershell + # Start in demo mode (using Asgardeo sandbox) + openmcpauthproxy.exe --demo + + # Start with Asgardeo integration + openmcpauthproxy.exe --asgardeo + + # Start in stdio mode + openmcpauthproxy.exe --demo --stdio + + # Enable debug logging + openmcpauthproxy.exe --demo --debug + + # See all available options + openmcpauthproxy.exe --help + ``` + +4. The proxy will start and display messages indicating it's running +5. To stop the proxy, press `Ctrl+C` in the command window From 56cdc96cb6df05be2ae1431148c9dd80f22b6556 Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath <43197743+shashimalcse@users.noreply.github.com> Date: Mon, 19 May 2025 22:44:07 +0530 Subject: [PATCH 08/13] fix asgardeo provider (#32) --- internal/authz/asgardeo.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/internal/authz/asgardeo.go b/internal/authz/asgardeo.go index a3c812c..9b8fdc5 100644 --- a/internal/authz/asgardeo.go +++ b/internal/authz/asgardeo.go @@ -13,14 +13,14 @@ import ( "time" "github.com/wso2/open-mcp-auth-proxy/internal/config" - "github.com/wso2/open-mcp-auth-proxy/internal/logging" + logger "github.com/wso2/open-mcp-auth-proxy/internal/logging" ) type asgardeoProvider struct { cfg *config.Config } -// NewAsgardeoProvider initializes a Provider for Asgardeo (demo mode). +// NewAsgardeoProvider initializes a Provider for Asgardeo. func NewAsgardeoProvider(cfg *config.Config) Provider { return &asgardeoProvider{cfg: cfg} } @@ -159,13 +159,19 @@ type RegisterResponse struct { } func (p *asgardeoProvider) createAsgardeoApplication(regReq RegisterRequest) error { + + orgName := p.cfg.Demo.OrgName + if p.cfg.Mode == "asgardeo" { + orgName = p.cfg.Asgardeo.OrgName + } + body := buildAsgardeoPayload(regReq) reqBytes, err := json.Marshal(body) if err != nil { return fmt.Errorf("failed to marshal Asgardeo request: %w", err) } - asgardeoAppURL := "https://api.asgardeo.io/t/" + p.cfg.Demo.OrgName + "/api/server/v1/applications" + asgardeoAppURL := "https://api.asgardeo.io/t/" + orgName + "/api/server/v1/applications" req, err := http.NewRequest("POST", asgardeoAppURL, bytes.NewBuffer(reqBytes)) if err != nil { return fmt.Errorf("failed to create Asgardeo API request: %w", err) @@ -195,6 +201,14 @@ func (p *asgardeoProvider) createAsgardeoApplication(regReq RegisterRequest) err } func (p *asgardeoProvider) getAsgardeoAdminToken() (string, error) { + + clientId := p.cfg.Demo.ClientID + clientSecret := p.cfg.Demo.ClientSecret + if p.cfg.Mode == "asgardeo" { + clientId = p.cfg.Asgardeo.ClientID + clientSecret = p.cfg.Asgardeo.ClientSecret + } + tokenURL := p.cfg.AuthServerBaseURL + "/token" formData := "grant_type=client_credentials&scope=internal_application_mgt_create internal_application_mgt_delete " + @@ -207,10 +221,10 @@ func (p *asgardeoProvider) getAsgardeoAdminToken() (string, error) { req.Header.Set("Content-Type", "application/x-www-form-urlencoded") // Sensitive data - should not be logged at INFO level - auth := p.cfg.Demo.ClientID + ":" + p.cfg.Demo.ClientSecret + auth := clientId + ":" + clientSecret req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) - - logger.Debug("Requesting admin token for Asgardeo with client ID: %s", p.cfg.Demo.ClientID) + + logger.Debug("Requesting admin token for Asgardeo with client ID: %s", clientId) tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, From 9e1316b4207c4842aaf1cb39722461324d1a98de Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Thu, 22 May 2025 16:42:16 +0530 Subject: [PATCH 09/13] Add unix and windows commands under basic usage --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 1158c7d..c63194e 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,16 @@ Open MCP Auth Proxy sits between MCP clients and your MCP server to: 2. Start the proxy in demo mode (uses pre-configured authentication with Asgardeo sandbox): +#### Linux/macOS: ```bash ./openmcpauthproxy --demo ``` +#### Windows: +```powershell +.\openmcpauthproxy.exe --demo +``` + > The repository comes with a default `config.yaml` file that contains the basic configuration: > > ```yaml From 2a0075b22ee90938061920525664961ded0ad6f7 Mon Sep 17 00:00:00 2001 From: Chiran Fernando Date: Thu, 22 May 2025 17:07:45 +0530 Subject: [PATCH 10/13] Streamline build from source steps --- README.md | 130 +++++++++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index c63194e..4694164 100644 --- a/README.md +++ b/README.md @@ -223,102 +223,100 @@ asgardeo: ``` ## Build from Source -### Prerequisites for Building +### Prerequisites * Go 1.20 or higher * Git -* Make (for Linux/macOS builds) +* Make (optional, for simplified builds) -### Building on Linux/macOS +### Clone and Build -1. Clone the repository: +1. **Clone the repository:** ```bash git clone https://github.com/wso2/open-mcp-auth-proxy cd open-mcp-auth-proxy ``` -2. Install dependencies: +2. **Install dependencies:** ```bash go get -v -t -d ./... ``` -3. Build for your platform: +3. **Build the application:** + + **Option A: Using Make** ```bash # Build for all platforms make all - # Or build for a specific platform - make build-linux # For Linux - make build-darwin # For macOS - make build-linux-arm # For ARM-based Linux - make build-windows # For Windows + # Or build for specific platforms + make build-linux # For Linux (x86_64) + make build-linux-arm # For ARM-based Linux + make build-darwin # For macOS + make build-windows # For Windows ``` -4. Find your build in the `build` directory: + **Option B: Manual build (works on all platforms)** ```bash - # For Linux - ./build/linux/openmcpauthproxy --demo + # Build for your current platform + go build -o openmcpauthproxy ./cmd/proxy - # For macOS - ./build/darwin/openmcpauthproxy --demo + # Cross-compile for other platforms + GOOS=linux GOARCH=amd64 go build -o openmcpauthproxy-linux ./cmd/proxy + GOOS=windows GOARCH=amd64 go build -o openmcpauthproxy.exe ./cmd/proxy + GOOS=darwin GOARCH=amd64 go build -o openmcpauthproxy-macos ./cmd/proxy ``` -### Building on Windows +### Run the Built Application -1. Clone the repository: - ```powershell - git clone https://github.com/wso2/open-mcp-auth-proxy - cd open-mcp-auth-proxy - ``` +After building, you'll find the executables in the `build` directory (when using Make) or in your project root (when building manually). -2. Install dependencies: - ```powershell - go get -v -t -d ./... - ``` +**Linux/macOS:** +```bash +# If built with Make +./build/linux/openmcpauthproxy --demo -3. Option 1: Build using Make if you have it installed: - ```powershell - make build-windows - ``` +# If built manually +./openmcpauthproxy --demo +``` - Option 2: Build manually without Make: - ```powershell - mkdir -p build\windows - go build -o build\windows\openmcpauthproxy.exe .\cmd\proxy - copy config.yaml build\windows\ - ``` +**Windows:** +```powershell +# If built with Make +.\build\windows\openmcpauthproxy.exe --demo -4. Run the built application: - ```powershell - cd build\windows - .\openmcpauthproxy.exe --demo - ``` +# If built manually +.\openmcpauthproxy.exe --demo +``` -### Starting the Proxy on Windows +### Available Command Line Options -1. Open Command Prompt or PowerShell -2. Navigate to the build directory: - ```powershell - cd build\windows - ``` +```bash +# Start in demo mode (using Asgardeo sandbox) +./openmcpauthproxy --demo -3. Run the executable with your desired options: - ```powershell - # Start in demo mode (using Asgardeo sandbox) - openmcpauthproxy.exe --demo - - # Start with Asgardeo integration - openmcpauthproxy.exe --asgardeo - - # Start in stdio mode - openmcpauthproxy.exe --demo --stdio - - # Enable debug logging - openmcpauthproxy.exe --demo --debug - - # See all available options - openmcpauthproxy.exe --help - ``` +# Start with your own Asgardeo organization +./openmcpauthproxy --asgardeo -4. The proxy will start and display messages indicating it's running -5. To stop the proxy, press `Ctrl+C` in the command window +# Use stdio transport mode instead of SSE +./openmcpauthproxy --demo --stdio + +# Enable debug logging +./openmcpauthproxy --demo --debug + +# Show all available options +./openmcpauthproxy --help +``` + +### Additional Make Targets + +If you're using Make, these additional targets are available: + +```bash +make test # Run tests +make coverage # Run tests with coverage report +make fmt # Format code with gofmt +make vet # Run go vet +make clean # Clean build artifacts +make help # Show all available targets +``` From 316370be1c0fd7204d2ca7af7e9d5dffe7c5eb9b Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath <43197743+shashimalcse@users.noreply.github.com> Date: Tue, 27 May 2025 13:27:02 +0530 Subject: [PATCH 11/13] Add StreambleHTTP support (#35) * Add StreambleHTTP support --- config.yaml | 7 +++--- internal/config/config.go | 44 +++++++++++++++++----------------- internal/config/config_test.go | 15 ++++-------- internal/proxy/proxy.go | 12 +++++----- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/config.yaml b/config.yaml index 5621195..427fc15 100644 --- a/config.yaml +++ b/config.yaml @@ -2,14 +2,15 @@ # Common configuration for all transport modes listen_port: 8080 -base_url: "http://localhost:8000" # Base URL for the MCP server -port: 8000 # Port for the MCP server +base_url: "http://localhost:3001" # Base URL for the MCP server +port: 3001 # Port for the MCP server timeout_seconds: 10 # Path configuration paths: sse: "/sse" # SSE endpoint path messages: "/messages/" # Messages endpoint path + streamable_http: "/mcp" # MCP endpoint path # Transport mode configuration transport_mode: "sse" # Options: "sse" or "stdio" @@ -28,7 +29,7 @@ path_mapping: # CORS configuration cors: allowed_origins: - - "http://localhost:5173" + - "http://127.0.0.1:6274" allowed_methods: - "GET" - "POST" diff --git a/internal/config/config.go b/internal/config/config.go index c50d9ed..c51688f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -19,15 +19,16 @@ const ( // Common path configuration for all transport modes type PathsConfig struct { - SSE string `yaml:"sse"` - Messages string `yaml:"messages"` + SSE string `yaml:"sse"` + Messages string `yaml:"messages"` + StreamableHTTP string `yaml:"streamable_http"` // Path for streamable HTTP requests } // StdioConfig contains stdio-specific configuration type StdioConfig struct { Enabled bool `yaml:"enabled"` - UserCommand string `yaml:"user_command"` // The command provided by the user - WorkDir string `yaml:"work_dir"` // Working directory (optional) + UserCommand string `yaml:"user_command"` // The command provided by the user + WorkDir string `yaml:"work_dir"` // Working directory (optional) Args []string `yaml:"args,omitempty"` // Additional arguments Env []string `yaml:"env,omitempty"` // Environment variables } @@ -85,18 +86,18 @@ type DefaultConfig struct { } type Config struct { - AuthServerBaseURL string - ListenPort int `yaml:"listen_port"` - BaseURL string `yaml:"base_url"` - Port int `yaml:"port"` - JWKSURL string - TimeoutSeconds int `yaml:"timeout_seconds"` - PathMapping map[string]string `yaml:"path_mapping"` - Mode string `yaml:"mode"` - CORSConfig CORSConfig `yaml:"cors"` - TransportMode TransportMode `yaml:"transport_mode"` - Paths PathsConfig `yaml:"paths"` - Stdio StdioConfig `yaml:"stdio"` + AuthServerBaseURL string + ListenPort int `yaml:"listen_port"` + BaseURL string `yaml:"base_url"` + Port int `yaml:"port"` + JWKSURL string + TimeoutSeconds int `yaml:"timeout_seconds"` + PathMapping map[string]string `yaml:"path_mapping"` + Mode string `yaml:"mode"` + CORSConfig CORSConfig `yaml:"cors"` + TransportMode TransportMode `yaml:"transport_mode"` + Paths PathsConfig `yaml:"paths"` + Stdio StdioConfig `yaml:"stdio"` // Nested config for Asgardeo Demo DemoConfig `yaml:"demo"` @@ -138,7 +139,7 @@ func (c *Config) Validate() error { // GetMCPPaths returns the list of paths that should be proxied to the MCP server func (c *Config) GetMCPPaths() []string { - return []string{c.Paths.SSE, c.Paths.Messages} + return []string{c.Paths.SSE, c.Paths.Messages, c.Paths.StreamableHTTP} } // BuildExecCommand constructs the full command string for execution in stdio mode @@ -147,7 +148,6 @@ func (c *Config) BuildExecCommand() string { return "" } - if runtime.GOOS == "windows" { // For Windows, we need to properly escape the inner command escapedCommand := strings.ReplaceAll(c.Stdio.UserCommand, `"`, `\"`) @@ -176,12 +176,12 @@ func LoadConfig(path string) (*Config, error) { if err := decoder.Decode(&cfg); err != nil { return nil, err } - + // Set default values if cfg.TimeoutSeconds == 0 { cfg.TimeoutSeconds = 15 // default } - + // Set default transport mode if not specified if cfg.TransportMode == "" { cfg.TransportMode = SSETransport // Default to SSE @@ -191,11 +191,11 @@ func LoadConfig(path string) (*Config, error) { if cfg.Port == 0 { cfg.Port = 8000 // default } - + // Validate the configuration if err := cfg.Validate(); err != nil { return nil, err } - + return &cfg, nil } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 20c0893..edf4182 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -136,20 +136,15 @@ func TestValidate(t *testing.T) { func TestGetMCPPaths(t *testing.T) { cfg := Config{ Paths: PathsConfig{ - SSE: "/custom-sse", - Messages: "/custom-messages", + SSE: "/custom-sse", + Messages: "/custom-messages", + StreamableHTTP: "/custom-streamable", }, } paths := cfg.GetMCPPaths() - if len(paths) != 2 { - t.Errorf("Expected 2 MCP paths, got %d", len(paths)) - } - if paths[0] != "/custom-sse" { - t.Errorf("Expected first path=/custom-sse, got %s", paths[0]) - } - if paths[1] != "/custom-messages" { - t.Errorf("Expected second path=/custom-messages, got %s", paths[1]) + if len(paths) != 3 { + t.Errorf("Expected 3 MCP paths, got %d", len(paths)) } } diff --git a/internal/proxy/proxy.go b/internal/proxy/proxy.go index 33a9ea3..f4d0dec 100644 --- a/internal/proxy/proxy.go +++ b/internal/proxy/proxy.go @@ -10,7 +10,7 @@ import ( "github.com/wso2/open-mcp-auth-proxy/internal/authz" "github.com/wso2/open-mcp-auth-proxy/internal/config" - "github.com/wso2/open-mcp-auth-proxy/internal/logging" + logger "github.com/wso2/open-mcp-auth-proxy/internal/logging" "github.com/wso2/open-mcp-auth-proxy/internal/util" ) @@ -106,7 +106,7 @@ func buildProxyHandler(cfg *config.Config, modifiers map[string]RequestModifier) logger.Error("Invalid auth server URL: %v", err) panic(err) // Fatal error that prevents startup } - + mcpBase, err := url.Parse(cfg.BaseURL) if err != nil { logger.Error("Invalid MCP server URL: %v", err) @@ -191,13 +191,13 @@ func buildProxyHandler(cfg *config.Config, modifiers map[string]RequestModifier) req.Host = targetURL.Host cleanHeaders := http.Header{} - + // Set proper origin header to match the target if isSSE { // For SSE, ensure origin matches the target req.Header.Set("Origin", targetURL.Scheme+"://"+targetURL.Host) } - + for k, v := range r.Header { // Skip hop-by-hop headers if skipHeader(k) { @@ -231,12 +231,12 @@ func buildProxyHandler(cfg *config.Config, modifiers map[string]RequestModifier) proxyHost: r.Host, targetHost: targetURL.Host, } - + // Set SSE-specific headers w.Header().Set("X-Accel-Buffering", "no") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") - + // Keep SSE connections open HandleSSE(w, r, rp) } else { From fdb81007d47f64bc9617b5bdacedbade598f6773 Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath <43197743+shashimalcse@users.noreply.github.com> Date: Wed, 4 Jun 2025 11:13:32 +0530 Subject: [PATCH 12/13] Fix multiple redirect uri format and filter supported grant types (#36) --- internal/authz/asgardeo.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/authz/asgardeo.go b/internal/authz/asgardeo.go index 9b8fdc5..eb26b83 100644 --- a/internal/authz/asgardeo.go +++ b/internal/authz/asgardeo.go @@ -113,6 +113,7 @@ func (p *asgardeoProvider) RegisterHandler() http.HandlerFunc { if err := p.createAsgardeoApplication(regReq); err != nil { logger.Warn("Asgardeo application creation failed: %v", err) + http.Error(w, "Failed to create application in Asgardeo", http.StatusInternalServerError) // Optionally http.Error(...) if you want to fail // or continue to return partial data. } @@ -269,6 +270,18 @@ func buildAsgardeoPayload(regReq RegisterRequest) map[string]interface{} { } appName += "-" + randomString(5) + // Build redirect URIs regex from list of redirect URIs : regexp=(https://app.example.com/callback1|https://app.example.com/callback2) + redirectURI := "regexp=(" + strings.Join(regReq.RedirectURIs, "|") + ")" + redirectURIs := []string{redirectURI} + + // Filter unsupported grant types + var grantTypes []string + for _, gt := range regReq.GrantTypes { + if gt == "authorization_code" || gt == "refresh_token" { + grantTypes = append(grantTypes, gt) + } + } + return map[string]interface{}{ "name": appName, "templateId": "custom-application-oidc", @@ -276,10 +289,10 @@ func buildAsgardeoPayload(regReq RegisterRequest) map[string]interface{} { "oidc": map[string]interface{}{ "clientId": regReq.ClientID, "clientSecret": regReq.ClientSecret, - "grantTypes": regReq.GrantTypes, - "callbackURLs": regReq.RedirectURIs, + "grantTypes": grantTypes, + "callbackURLs": redirectURIs, "allowedOrigins": []string{}, - "publicClient": false, + "publicClient": true, "pkce": map[string]bool{ "mandatory": true, "supportPlainTransformAlgorithm": true, From 53e0fa65a1c0cb2f4e3972bd66e9cf3dada8cda6 Mon Sep 17 00:00:00 2001 From: Pavindu Lakshan Date: Sun, 22 Jun 2025 20:52:01 +0530 Subject: [PATCH 13/13] Update release workflow action --- .github/scripts/release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/release.sh b/.github/scripts/release.sh index 2a1f6a9..52b024d 100644 --- a/.github/scripts/release.sh +++ b/.github/scripts/release.sh @@ -51,7 +51,7 @@ else fi # Extract current version. -CURRENT_VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0") +CURRENT_VERSION=$(git tag --sort=-v:refname | head -n 1 | sed 's/^v//' || echo "0.0.0") IFS='.' read -r MAJOR MINOR PATCH <<< "${CURRENT_VERSION}" # Determine which part to increment