mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 05:01:23 +00:00
refactor(gateway): unify credential precedence across entrypoints
This commit is contained in:
@@ -120,6 +120,24 @@ describe("gateway auth", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps gateway auth config values ahead of env overrides", () => {
|
||||
expect(
|
||||
resolveGatewayAuth({
|
||||
authConfig: {
|
||||
token: "config-token",
|
||||
password: "config-password",
|
||||
},
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
OPENCLAW_GATEWAY_PASSWORD: "env-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
}),
|
||||
).toMatchObject({
|
||||
token: "config-token",
|
||||
password: "config-password",
|
||||
});
|
||||
});
|
||||
|
||||
it("resolves explicit auth mode none from config", () => {
|
||||
expect(
|
||||
resolveGatewayAuth({
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
type AuthRateLimiter,
|
||||
type RateLimitCheckResult,
|
||||
} from "./auth-rate-limit.js";
|
||||
import { resolveGatewayCredentialsFromValues } from "./credentials.js";
|
||||
import {
|
||||
isLocalishHost,
|
||||
isLoopbackAddress,
|
||||
@@ -242,8 +243,16 @@ export function resolveGatewayAuth(params: {
|
||||
}
|
||||
}
|
||||
const env = params.env ?? process.env;
|
||||
const token = authConfig.token ?? env.OPENCLAW_GATEWAY_TOKEN ?? undefined;
|
||||
const password = authConfig.password ?? env.OPENCLAW_GATEWAY_PASSWORD ?? undefined;
|
||||
const resolvedCredentials = resolveGatewayCredentialsFromValues({
|
||||
configToken: authConfig.token,
|
||||
configPassword: authConfig.password,
|
||||
env,
|
||||
includeLegacyEnv: false,
|
||||
tokenPrecedence: "config-first",
|
||||
passwordPrecedence: "config-first",
|
||||
});
|
||||
const token = resolvedCredentials.token;
|
||||
const password = resolvedCredentials.password;
|
||||
const trustedProxy = authConfig.trustedProxy;
|
||||
|
||||
let mode: ResolvedGatewayAuth["mode"];
|
||||
|
||||
@@ -287,6 +287,29 @@ describe("GatewayClient close handling", () => {
|
||||
expect(onClose).toHaveBeenCalledWith(1008, "unauthorized: signature invalid");
|
||||
client.stop();
|
||||
});
|
||||
|
||||
it("does not clear persisted device auth when explicit shared token is provided", () => {
|
||||
const onClose = vi.fn();
|
||||
const identity: DeviceIdentity = {
|
||||
deviceId: "dev-5",
|
||||
privateKeyPem: "private-key",
|
||||
publicKeyPem: "public-key",
|
||||
};
|
||||
const client = new GatewayClient({
|
||||
url: "ws://127.0.0.1:18789",
|
||||
deviceIdentity: identity,
|
||||
token: "shared-token",
|
||||
onClose,
|
||||
});
|
||||
|
||||
client.start();
|
||||
getLatestWs().emitClose(1008, "unauthorized: device token mismatch");
|
||||
|
||||
expect(clearDeviceAuthTokenMock).not.toHaveBeenCalled();
|
||||
expect(clearDevicePairingMock).not.toHaveBeenCalled();
|
||||
expect(onClose).toHaveBeenCalledWith(1008, "unauthorized: device token mismatch");
|
||||
client.stop();
|
||||
});
|
||||
});
|
||||
|
||||
describe("GatewayClient connect auth payload", () => {
|
||||
|
||||
@@ -179,10 +179,14 @@ export class GatewayClient {
|
||||
this.ws.on("close", (code, reason) => {
|
||||
const reasonText = rawDataToString(reason);
|
||||
this.ws = null;
|
||||
// If closed due to device token mismatch, clear the stored token and pairing so next attempt can get a fresh one
|
||||
// Clear persisted device auth state only when device-token auth was active.
|
||||
// Shared token/password failures can return the same close reason but should
|
||||
// not erase a valid cached device token.
|
||||
if (
|
||||
code === 1008 &&
|
||||
reasonText.toLowerCase().includes("device token mismatch") &&
|
||||
!this.opts.token &&
|
||||
!this.opts.password &&
|
||||
this.opts.deviceIdentity
|
||||
) {
|
||||
const deviceId = this.opts.deviceIdentity.deviceId;
|
||||
|
||||
171
src/gateway/credential-precedence.parity.test.ts
Normal file
171
src/gateway/credential-precedence.parity.test.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveGatewayProbeAuth as resolveStatusGatewayProbeAuth } from "../commands/status.gateway-probe.js";
|
||||
import type { OpenClawConfig, loadConfig } from "../config/config.js";
|
||||
import { resolveGatewayAuth } from "./auth.js";
|
||||
import { resolveGatewayCredentialsFromConfig } from "./credentials.js";
|
||||
import { resolveGatewayProbeAuth } from "./probe-auth.js";
|
||||
|
||||
type ExpectedCredentialSet = {
|
||||
call: { token?: string; password?: string };
|
||||
probe: { token?: string; password?: string };
|
||||
status: { token?: string; password?: string };
|
||||
auth: { token?: string; password?: string };
|
||||
};
|
||||
|
||||
type TestCase = {
|
||||
name: string;
|
||||
cfg: OpenClawConfig;
|
||||
env: NodeJS.ProcessEnv;
|
||||
expected: ExpectedCredentialSet;
|
||||
};
|
||||
|
||||
function withGatewayAuthEnv<T>(env: NodeJS.ProcessEnv, fn: () => T): T {
|
||||
const keys = [
|
||||
"OPENCLAW_GATEWAY_TOKEN",
|
||||
"OPENCLAW_GATEWAY_PASSWORD",
|
||||
"CLAWDBOT_GATEWAY_TOKEN",
|
||||
"CLAWDBOT_GATEWAY_PASSWORD",
|
||||
] as const;
|
||||
const previous = new Map<string, string | undefined>();
|
||||
for (const key of keys) {
|
||||
previous.set(key, process.env[key]);
|
||||
const nextValue = env[key];
|
||||
if (typeof nextValue === "string") {
|
||||
process.env[key] = nextValue;
|
||||
} else {
|
||||
delete process.env[key];
|
||||
}
|
||||
}
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
for (const key of keys) {
|
||||
const value = previous.get(key);
|
||||
if (typeof value === "string") {
|
||||
process.env[key] = value;
|
||||
} else {
|
||||
delete process.env[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("gateway credential precedence parity", () => {
|
||||
const cases: TestCase[] = [
|
||||
{
|
||||
name: "local mode: env overrides config for call/probe/status, auth remains config-first",
|
||||
cfg: {
|
||||
gateway: {
|
||||
mode: "local",
|
||||
auth: {
|
||||
token: "config-token",
|
||||
password: "config-password",
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
OPENCLAW_GATEWAY_PASSWORD: "env-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
expected: {
|
||||
call: { token: "env-token", password: "env-password" },
|
||||
probe: { token: "env-token", password: "env-password" },
|
||||
status: { token: "env-token", password: "env-password" },
|
||||
auth: { token: "config-token", password: "config-password" },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remote mode with remote token configured",
|
||||
cfg: {
|
||||
gateway: {
|
||||
mode: "remote",
|
||||
remote: {
|
||||
token: "remote-token",
|
||||
password: "remote-password",
|
||||
},
|
||||
auth: {
|
||||
token: "local-token",
|
||||
password: "local-password",
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
OPENCLAW_GATEWAY_PASSWORD: "env-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
expected: {
|
||||
call: { token: "remote-token", password: "env-password" },
|
||||
probe: { token: "remote-token", password: "env-password" },
|
||||
status: { token: "remote-token", password: "env-password" },
|
||||
auth: { token: "local-token", password: "local-password" },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remote mode without remote token keeps remote probe/status strict",
|
||||
cfg: {
|
||||
gateway: {
|
||||
mode: "remote",
|
||||
remote: {
|
||||
password: "remote-password",
|
||||
},
|
||||
auth: {
|
||||
token: "local-token",
|
||||
password: "local-password",
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
OPENCLAW_GATEWAY_PASSWORD: "env-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
expected: {
|
||||
call: { token: "env-token", password: "env-password" },
|
||||
probe: { token: undefined, password: "env-password" },
|
||||
status: { token: undefined, password: "env-password" },
|
||||
auth: { token: "local-token", password: "local-password" },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy env vars are ignored by probe/status/auth but still supported for call path",
|
||||
cfg: {
|
||||
gateway: {
|
||||
mode: "local",
|
||||
auth: {},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
env: {
|
||||
CLAWDBOT_GATEWAY_TOKEN: "legacy-token",
|
||||
CLAWDBOT_GATEWAY_PASSWORD: "legacy-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
expected: {
|
||||
call: { token: "legacy-token", password: "legacy-password" },
|
||||
probe: { token: undefined, password: undefined },
|
||||
status: { token: undefined, password: undefined },
|
||||
auth: { token: undefined, password: undefined },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
it.each(cases)("$name", ({ cfg, env, expected }) => {
|
||||
const mode = cfg.gateway?.mode === "remote" ? "remote" : "local";
|
||||
const call = resolveGatewayCredentialsFromConfig({
|
||||
cfg,
|
||||
env,
|
||||
});
|
||||
const probe = resolveGatewayProbeAuth({
|
||||
cfg,
|
||||
mode,
|
||||
env,
|
||||
});
|
||||
const status = withGatewayAuthEnv(env, () => resolveStatusGatewayProbeAuth(cfg));
|
||||
const auth = resolveGatewayAuth({
|
||||
authConfig: cfg.gateway?.auth,
|
||||
env,
|
||||
});
|
||||
|
||||
expect(call).toEqual(expected.call);
|
||||
expect(probe).toEqual(expected.probe);
|
||||
expect(status).toEqual(expected.status);
|
||||
expect({ token: auth.token, password: auth.password }).toEqual(expected.auth);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveGatewayCredentialsFromConfig } from "./credentials.js";
|
||||
import {
|
||||
resolveGatewayCredentialsFromConfig,
|
||||
resolveGatewayCredentialsFromValues,
|
||||
} from "./credentials.js";
|
||||
|
||||
function cfg(input: Partial<OpenClawConfig>): OpenClawConfig {
|
||||
return input as OpenClawConfig;
|
||||
@@ -77,7 +80,7 @@ describe("resolveGatewayCredentialsFromConfig", () => {
|
||||
});
|
||||
expect(resolved).toEqual({
|
||||
token: "remote-token",
|
||||
password: "remote-password",
|
||||
password: "env-password",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -121,4 +124,72 @@ describe("resolveGatewayCredentialsFromConfig", () => {
|
||||
password: "env-password",
|
||||
});
|
||||
});
|
||||
|
||||
it("supports remote-only token fallback for strict remote override call sites", () => {
|
||||
const resolved = resolveGatewayCredentialsFromConfig({
|
||||
cfg: cfg({
|
||||
gateway: {
|
||||
mode: "remote",
|
||||
remote: { url: "wss://gateway.example" },
|
||||
auth: { token: "local-token" },
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
} as NodeJS.ProcessEnv,
|
||||
remoteTokenFallback: "remote-only",
|
||||
});
|
||||
expect(resolved.token).toBeUndefined();
|
||||
});
|
||||
|
||||
it("can disable legacy CLAWDBOT env fallback", () => {
|
||||
const resolved = resolveGatewayCredentialsFromConfig({
|
||||
cfg: cfg({
|
||||
gateway: {
|
||||
mode: "local",
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
CLAWDBOT_GATEWAY_TOKEN: "legacy-token",
|
||||
CLAWDBOT_GATEWAY_PASSWORD: "legacy-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
includeLegacyEnv: false,
|
||||
});
|
||||
expect(resolved).toEqual({ token: undefined, password: undefined });
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveGatewayCredentialsFromValues", () => {
|
||||
it("supports config-first precedence for token/password", () => {
|
||||
const resolved = resolveGatewayCredentialsFromValues({
|
||||
configToken: "config-token",
|
||||
configPassword: "config-password",
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
OPENCLAW_GATEWAY_PASSWORD: "env-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
includeLegacyEnv: false,
|
||||
tokenPrecedence: "config-first",
|
||||
passwordPrecedence: "config-first",
|
||||
});
|
||||
expect(resolved).toEqual({
|
||||
token: "config-token",
|
||||
password: "config-password",
|
||||
});
|
||||
});
|
||||
|
||||
it("uses env-first precedence by default", () => {
|
||||
const resolved = resolveGatewayCredentialsFromValues({
|
||||
configToken: "config-token",
|
||||
configPassword: "config-password",
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "env-token",
|
||||
OPENCLAW_GATEWAY_PASSWORD: "env-password",
|
||||
} as NodeJS.ProcessEnv,
|
||||
});
|
||||
expect(resolved).toEqual({
|
||||
token: "env-token",
|
||||
password: "env-password",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,12 @@ export type ResolvedGatewayCredentials = {
|
||||
password?: string;
|
||||
};
|
||||
|
||||
function trimToUndefined(value: unknown): string | undefined {
|
||||
export type GatewayCredentialMode = "local" | "remote";
|
||||
export type GatewayCredentialPrecedence = "env-first" | "config-first";
|
||||
export type GatewayRemoteCredentialPrecedence = "remote-first" | "env-first";
|
||||
export type GatewayRemoteCredentialFallback = "remote-env-local" | "remote-only";
|
||||
|
||||
export function trimToUndefined(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
@@ -18,14 +23,88 @@ function trimToUndefined(value: unknown): string | undefined {
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function firstDefined(values: Array<string | undefined>): string | undefined {
|
||||
for (const value of values) {
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function readGatewayTokenEnv(
|
||||
env: NodeJS.ProcessEnv,
|
||||
includeLegacyEnv: boolean,
|
||||
): string | undefined {
|
||||
const primary = trimToUndefined(env.OPENCLAW_GATEWAY_TOKEN);
|
||||
if (primary) {
|
||||
return primary;
|
||||
}
|
||||
if (!includeLegacyEnv) {
|
||||
return undefined;
|
||||
}
|
||||
return trimToUndefined(env.CLAWDBOT_GATEWAY_TOKEN);
|
||||
}
|
||||
|
||||
function readGatewayPasswordEnv(
|
||||
env: NodeJS.ProcessEnv,
|
||||
includeLegacyEnv: boolean,
|
||||
): string | undefined {
|
||||
const primary = trimToUndefined(env.OPENCLAW_GATEWAY_PASSWORD);
|
||||
if (primary) {
|
||||
return primary;
|
||||
}
|
||||
if (!includeLegacyEnv) {
|
||||
return undefined;
|
||||
}
|
||||
return trimToUndefined(env.CLAWDBOT_GATEWAY_PASSWORD);
|
||||
}
|
||||
|
||||
export function resolveGatewayCredentialsFromValues(params: {
|
||||
configToken?: string;
|
||||
configPassword?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
includeLegacyEnv?: boolean;
|
||||
tokenPrecedence?: GatewayCredentialPrecedence;
|
||||
passwordPrecedence?: GatewayCredentialPrecedence;
|
||||
}): ResolvedGatewayCredentials {
|
||||
const env = params.env ?? process.env;
|
||||
const includeLegacyEnv = params.includeLegacyEnv ?? true;
|
||||
const envToken = readGatewayTokenEnv(env, includeLegacyEnv);
|
||||
const envPassword = readGatewayPasswordEnv(env, includeLegacyEnv);
|
||||
const configToken = trimToUndefined(params.configToken);
|
||||
const configPassword = trimToUndefined(params.configPassword);
|
||||
const tokenPrecedence = params.tokenPrecedence ?? "env-first";
|
||||
const passwordPrecedence = params.passwordPrecedence ?? "env-first";
|
||||
|
||||
const token =
|
||||
tokenPrecedence === "config-first"
|
||||
? firstDefined([configToken, envToken])
|
||||
: firstDefined([envToken, configToken]);
|
||||
const password =
|
||||
passwordPrecedence === "config-first"
|
||||
? firstDefined([configPassword, envPassword])
|
||||
: firstDefined([envPassword, configPassword]);
|
||||
|
||||
return { token, password };
|
||||
}
|
||||
|
||||
export function resolveGatewayCredentialsFromConfig(params: {
|
||||
cfg: OpenClawConfig;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
explicitAuth?: ExplicitGatewayAuth;
|
||||
urlOverride?: string;
|
||||
remotePasswordPrecedence?: "remote-first" | "env-first";
|
||||
modeOverride?: GatewayCredentialMode;
|
||||
includeLegacyEnv?: boolean;
|
||||
localTokenPrecedence?: GatewayCredentialPrecedence;
|
||||
localPasswordPrecedence?: GatewayCredentialPrecedence;
|
||||
remoteTokenPrecedence?: GatewayRemoteCredentialPrecedence;
|
||||
remotePasswordPrecedence?: GatewayRemoteCredentialPrecedence;
|
||||
remoteTokenFallback?: GatewayRemoteCredentialFallback;
|
||||
remotePasswordFallback?: GatewayRemoteCredentialFallback;
|
||||
}): ResolvedGatewayCredentials {
|
||||
const env = params.env ?? process.env;
|
||||
const includeLegacyEnv = params.includeLegacyEnv ?? true;
|
||||
const explicitToken = trimToUndefined(params.explicitAuth?.token);
|
||||
const explicitPassword = trimToUndefined(params.explicitAuth?.password);
|
||||
if (explicitToken || explicitPassword) {
|
||||
@@ -35,27 +114,49 @@ export function resolveGatewayCredentialsFromConfig(params: {
|
||||
return {};
|
||||
}
|
||||
|
||||
const isRemoteMode = params.cfg.gateway?.mode === "remote";
|
||||
const remote = isRemoteMode ? params.cfg.gateway?.remote : undefined;
|
||||
|
||||
const envToken =
|
||||
trimToUndefined(env.OPENCLAW_GATEWAY_TOKEN) ?? trimToUndefined(env.CLAWDBOT_GATEWAY_TOKEN);
|
||||
const envPassword =
|
||||
trimToUndefined(env.OPENCLAW_GATEWAY_PASSWORD) ??
|
||||
trimToUndefined(env.CLAWDBOT_GATEWAY_PASSWORD);
|
||||
const mode: GatewayCredentialMode =
|
||||
params.modeOverride ?? (params.cfg.gateway?.mode === "remote" ? "remote" : "local");
|
||||
const remote = mode === "remote" ? params.cfg.gateway?.remote : undefined;
|
||||
const envToken = readGatewayTokenEnv(env, includeLegacyEnv);
|
||||
const envPassword = readGatewayPasswordEnv(env, includeLegacyEnv);
|
||||
|
||||
const remoteToken = trimToUndefined(remote?.token);
|
||||
const remotePassword = trimToUndefined(remote?.password);
|
||||
const localToken = trimToUndefined(params.cfg.gateway?.auth?.token);
|
||||
const localPassword = trimToUndefined(params.cfg.gateway?.auth?.password);
|
||||
|
||||
const token = isRemoteMode ? (remoteToken ?? envToken ?? localToken) : (envToken ?? localToken);
|
||||
const passwordPrecedence = params.remotePasswordPrecedence ?? "remote-first";
|
||||
const password = isRemoteMode
|
||||
? passwordPrecedence === "env-first"
|
||||
? (envPassword ?? remotePassword ?? localPassword)
|
||||
: (remotePassword ?? envPassword ?? localPassword)
|
||||
: (envPassword ?? localPassword);
|
||||
const localTokenPrecedence = params.localTokenPrecedence ?? "env-first";
|
||||
const localPasswordPrecedence = params.localPasswordPrecedence ?? "env-first";
|
||||
|
||||
if (mode === "local") {
|
||||
const localResolved = resolveGatewayCredentialsFromValues({
|
||||
configToken: localToken,
|
||||
configPassword: localPassword,
|
||||
env,
|
||||
includeLegacyEnv,
|
||||
tokenPrecedence: localTokenPrecedence,
|
||||
passwordPrecedence: localPasswordPrecedence,
|
||||
});
|
||||
return localResolved;
|
||||
}
|
||||
|
||||
const remoteTokenFallback = params.remoteTokenFallback ?? "remote-env-local";
|
||||
const remotePasswordFallback = params.remotePasswordFallback ?? "remote-env-local";
|
||||
const remoteTokenPrecedence = params.remoteTokenPrecedence ?? "remote-first";
|
||||
const remotePasswordPrecedence = params.remotePasswordPrecedence ?? "env-first";
|
||||
|
||||
const token =
|
||||
remoteTokenFallback === "remote-only"
|
||||
? remoteToken
|
||||
: remoteTokenPrecedence === "env-first"
|
||||
? firstDefined([envToken, remoteToken, localToken])
|
||||
: firstDefined([remoteToken, envToken, localToken]);
|
||||
const password =
|
||||
remotePasswordFallback === "remote-only"
|
||||
? remotePassword
|
||||
: remotePasswordPrecedence === "env-first"
|
||||
? firstDefined([envPassword, remotePassword, localPassword])
|
||||
: firstDefined([remotePassword, envPassword, localPassword]);
|
||||
|
||||
return { token, password };
|
||||
}
|
||||
|
||||
@@ -1,32 +1,16 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveGatewayCredentialsFromConfig } from "./credentials.js";
|
||||
|
||||
export function resolveGatewayProbeAuth(params: {
|
||||
cfg: OpenClawConfig;
|
||||
mode: "local" | "remote";
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): { token?: string; password?: string } {
|
||||
const env = params.env ?? process.env;
|
||||
const authToken = params.cfg.gateway?.auth?.token;
|
||||
const authPassword = params.cfg.gateway?.auth?.password;
|
||||
const remote = params.cfg.gateway?.remote;
|
||||
|
||||
const token =
|
||||
params.mode === "remote"
|
||||
? typeof remote?.token === "string" && remote.token.trim()
|
||||
? remote.token.trim()
|
||||
: undefined
|
||||
: env.OPENCLAW_GATEWAY_TOKEN?.trim() ||
|
||||
(typeof authToken === "string" && authToken.trim() ? authToken.trim() : undefined);
|
||||
|
||||
const password =
|
||||
env.OPENCLAW_GATEWAY_PASSWORD?.trim() ||
|
||||
(params.mode === "remote"
|
||||
? typeof remote?.password === "string" && remote.password.trim()
|
||||
? remote.password.trim()
|
||||
: undefined
|
||||
: typeof authPassword === "string" && authPassword.trim()
|
||||
? authPassword.trim()
|
||||
: undefined);
|
||||
|
||||
return { token, password };
|
||||
return resolveGatewayCredentialsFromConfig({
|
||||
cfg: params.cfg,
|
||||
env: params.env,
|
||||
modeOverride: params.mode,
|
||||
includeLegacyEnv: false,
|
||||
remoteTokenFallback: "remote-only",
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user