mirror of https://github.com/openclaw/openclaw.git
refactor: share handshake auth helper builders
This commit is contained in:
parent
6ecc184637
commit
4674fbf923
|
|
@ -10,24 +10,21 @@ import {
|
|||
shouldSkipBackendSelfPairing,
|
||||
} from "./handshake-auth-helpers.js";
|
||||
|
||||
function createRateLimiter(): AuthRateLimiter {
|
||||
return {
|
||||
check: () => ({ allowed: true, remaining: 1, retryAfterMs: 0 }),
|
||||
reset: () => {},
|
||||
recordFailure: () => {},
|
||||
size: () => 0,
|
||||
prune: () => {},
|
||||
dispose: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
describe("handshake auth helpers", () => {
|
||||
it("pins browser-origin loopback clients to the synthetic rate-limit ip", () => {
|
||||
const rateLimiter: AuthRateLimiter = {
|
||||
check: () => ({ allowed: true, remaining: 1, retryAfterMs: 0 }),
|
||||
reset: () => {},
|
||||
recordFailure: () => {},
|
||||
size: () => 0,
|
||||
prune: () => {},
|
||||
dispose: () => {},
|
||||
};
|
||||
const browserRateLimiter: AuthRateLimiter = {
|
||||
check: () => ({ allowed: true, remaining: 1, retryAfterMs: 0 }),
|
||||
reset: () => {},
|
||||
recordFailure: () => {},
|
||||
size: () => 0,
|
||||
prune: () => {},
|
||||
dispose: () => {},
|
||||
};
|
||||
const rateLimiter = createRateLimiter();
|
||||
const browserRateLimiter = createRateLimiter();
|
||||
const resolved = resolveHandshakeBrowserSecurityContext({
|
||||
requestOrigin: "https://app.example",
|
||||
clientIp: "127.0.0.1",
|
||||
|
|
|
|||
|
|
@ -91,6 +91,23 @@ function resolveSignatureToken(connectParams: ConnectParams): string | null {
|
|||
);
|
||||
}
|
||||
|
||||
function buildUnauthorizedHandshakeContext(params: {
|
||||
authProvided: AuthProvidedKind;
|
||||
canRetryWithDeviceToken: boolean;
|
||||
recommendedNextStep:
|
||||
| "retry_with_device_token"
|
||||
| "update_auth_configuration"
|
||||
| "update_auth_credentials"
|
||||
| "wait_then_retry"
|
||||
| "review_auth_configuration";
|
||||
}) {
|
||||
return {
|
||||
authProvided: params.authProvided,
|
||||
canRetryWithDeviceToken: params.canRetryWithDeviceToken,
|
||||
recommendedNextStep: params.recommendedNextStep,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveDeviceSignaturePayloadVersion(params: {
|
||||
device: {
|
||||
id: string;
|
||||
|
|
@ -104,7 +121,7 @@ export function resolveDeviceSignaturePayloadVersion(params: {
|
|||
nonce: string;
|
||||
}): "v3" | "v2" | null {
|
||||
const signatureToken = resolveSignatureToken(params.connectParams);
|
||||
const payloadV3 = buildDeviceAuthPayloadV3({
|
||||
const basePayload = {
|
||||
deviceId: params.device.id,
|
||||
clientId: params.connectParams.client.id,
|
||||
clientMode: params.connectParams.client.mode,
|
||||
|
|
@ -113,6 +130,9 @@ export function resolveDeviceSignaturePayloadVersion(params: {
|
|||
signedAtMs: params.signedAtMs,
|
||||
token: signatureToken,
|
||||
nonce: params.nonce,
|
||||
};
|
||||
const payloadV3 = buildDeviceAuthPayloadV3({
|
||||
...basePayload,
|
||||
platform: params.connectParams.client.platform,
|
||||
deviceFamily: params.connectParams.client.deviceFamily,
|
||||
});
|
||||
|
|
@ -120,16 +140,7 @@ export function resolveDeviceSignaturePayloadVersion(params: {
|
|||
return "v3";
|
||||
}
|
||||
|
||||
const payloadV2 = buildDeviceAuthPayload({
|
||||
deviceId: params.device.id,
|
||||
clientId: params.connectParams.client.id,
|
||||
clientMode: params.connectParams.client.mode,
|
||||
role: params.role,
|
||||
scopes: params.scopes,
|
||||
signedAtMs: params.signedAtMs,
|
||||
token: signatureToken,
|
||||
nonce: params.nonce,
|
||||
});
|
||||
const payloadV2 = buildDeviceAuthPayload(basePayload);
|
||||
if (verifyDeviceSignature(params.device.publicKey, payloadV2, params.device.signature)) {
|
||||
return "v2";
|
||||
}
|
||||
|
|
@ -171,41 +182,41 @@ export function resolveUnauthorizedHandshakeContext(params: {
|
|||
authProvided === "token" &&
|
||||
!params.connectAuth?.deviceToken;
|
||||
if (canRetryWithDeviceToken) {
|
||||
return {
|
||||
return buildUnauthorizedHandshakeContext({
|
||||
authProvided,
|
||||
canRetryWithDeviceToken,
|
||||
recommendedNextStep: "retry_with_device_token",
|
||||
};
|
||||
});
|
||||
}
|
||||
switch (params.failedAuth.reason) {
|
||||
case "token_missing":
|
||||
case "token_missing_config":
|
||||
case "password_missing":
|
||||
case "password_missing_config":
|
||||
return {
|
||||
return buildUnauthorizedHandshakeContext({
|
||||
authProvided,
|
||||
canRetryWithDeviceToken,
|
||||
recommendedNextStep: "update_auth_configuration",
|
||||
};
|
||||
});
|
||||
case "token_mismatch":
|
||||
case "password_mismatch":
|
||||
case "device_token_mismatch":
|
||||
return {
|
||||
return buildUnauthorizedHandshakeContext({
|
||||
authProvided,
|
||||
canRetryWithDeviceToken,
|
||||
recommendedNextStep: "update_auth_credentials",
|
||||
};
|
||||
});
|
||||
case "rate_limited":
|
||||
return {
|
||||
return buildUnauthorizedHandshakeContext({
|
||||
authProvided,
|
||||
canRetryWithDeviceToken,
|
||||
recommendedNextStep: "wait_then_retry",
|
||||
};
|
||||
});
|
||||
default:
|
||||
return {
|
||||
return buildUnauthorizedHandshakeContext({
|
||||
authProvided,
|
||||
canRetryWithDeviceToken,
|
||||
recommendedNextStep: "review_auth_configuration",
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue