diff --git a/internal/acp/config.go b/internal/acp/config.go index 0ffbe5e..0f52fa8 100644 --- a/internal/acp/config.go +++ b/internal/acp/config.go @@ -53,13 +53,17 @@ func resolveURL(yamlVal string, envKeys ...string) string { } func bridgeUpstreamAuthorizationHeader() string { - token := strings.TrimSpace(shared.EnvOrDefault("BRIDGE_AUTH_TOKEN", "")) + token := bridgeSharedAuthToken() if token != "" && !strings.HasPrefix(strings.ToLower(token), "bearer ") { return "Bearer " + token } return token } +func bridgeSharedAuthToken() string { + return strings.TrimSpace(shared.EnvOrDefault("BRIDGE_AUTH_TOKEN", "")) +} + func newProductionProviderCatalog() (*BridgeConfig, map[string]syncedProvider, []string) { config := loadBridgeConfig() authorizationHeader := bridgeUpstreamAuthorizationHeader() diff --git a/internal/acp/gateway.go b/internal/acp/gateway.go index d505396..61e2cca 100644 --- a/internal/acp/gateway.go +++ b/internal/acp/gateway.go @@ -133,7 +133,7 @@ func applyProductionGatewayRouting( Port: port, TLS: tls, } - request.Auth.Token = strings.TrimSpace(bridgeUpstreamAuthorizationHeader()) + request.Auth.Token = bridgeSharedAuthToken() request.Auth.Password = "" request.ConnectAuthMode = "shared-token" request.ConnectAuthFields = []string{"token"} diff --git a/internal/acp/routing_test.go b/internal/acp/routing_test.go index 7e6d607..c24e2fa 100644 --- a/internal/acp/routing_test.go +++ b/internal/acp/routing_test.go @@ -643,6 +643,18 @@ func newAcpFakeOpenClawGateway(t *testing.T) *acpFakeOpenClawGateway { }) return } + if got, want := shared.StringArg(shared.AsMap(params["auth"]), "token", ""), os.Getenv("BRIDGE_AUTH_TOKEN"); got != want { + _ = conn.WriteJSON(map[string]any{ + "type": "res", + "id": id, + "ok": false, + "error": map[string]any{ + "code": "INVALID_REQUEST", + "message": "unauthorized: gateway token mismatch", + }, + }) + return + } fake.lastConnectClient.Store(shared.AsMap(params["client"])) _ = conn.WriteJSON(map[string]any{ "type": "res",