Download src/gateway/server/plugin-node-capability-auth.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 3.56 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/gateway/server/plugin-node-capability-auth.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/gateway/server/plugin-node-capability-auth.ts
-
curl -L -o plugin-node-capability-auth.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/gateway/server/plugin-node-capability-auth.ts
3.56 kB
| // Plugin node capability auth lets node-issued route capabilities supplement normal bearer gateway auth. | |
| import type { IncomingMessage } from "node:http"; | |
| import { AUTH_RATE_LIMIT_SCOPE_SHARED_SECRET, type AuthRateLimiter } from "../auth-rate-limit.js"; | |
| import { | |
| authorizeHttpGatewayConnect, | |
| type GatewayAuthResult, | |
| type ResolvedGatewayAuth, | |
| } from "../auth.js"; | |
| import { getBearerToken, resolveHttpBrowserOriginPolicy } from "../http-auth-utils.js"; | |
| import { | |
| prepareGatewayIngressAttribution, | |
| PROXY_ATTRIBUTION_REQUIRED_REASON, | |
| } from "../ingress-attribution.js"; | |
| import { | |
| hasAuthorizedPluginNodeCapability, | |
| type PluginNodeCapabilitySurface, | |
| } from "../plugin-node-capability.js"; | |
| import { withSerializedCredentialFallbackAttempt } from "../rate-limit-attempt-serialization.js"; | |
| import type { GatewayWsClient } from "./ws-types.js"; | |
| /** | |
| * Authorizes plugin HTTP routes that can be reached by node-issued capabilities. | |
| */ | |
| export async function authorizePluginNodeCapabilityRequest(params: { | |
| req: IncomingMessage; | |
| auth: ResolvedGatewayAuth; | |
| trustedProxies: string[]; | |
| allowRealIpFallback: boolean; | |
| clients: Set<GatewayWsClient>; | |
| nodeCapability: PluginNodeCapabilitySurface; | |
| capability?: string; | |
| malformedScopedPath?: boolean; | |
| rateLimiter?: AuthRateLimiter; | |
| }): Promise<GatewayAuthResult> { | |
| const { | |
| req, | |
| auth, | |
| trustedProxies, | |
| allowRealIpFallback, | |
| clients, | |
| nodeCapability, | |
| capability, | |
| malformedScopedPath, | |
| rateLimiter, | |
| } = params; | |
| if (malformedScopedPath) { | |
| return { ok: false, reason: "unauthorized" }; | |
| } | |
| const attribution = prepareGatewayIngressAttribution({ | |
| req, | |
| trustedProxies, | |
| allowRealIpFallback, | |
| }); | |
| if (attribution.kind === "unattributable-proxy") { | |
| return { ok: false, reason: PROXY_ATTRIBUTION_REQUIRED_REASON }; | |
| } | |
| const token = getBearerToken(req); | |
| const run = async (): Promise<GatewayAuthResult> => { | |
| let lastAuthFailure: GatewayAuthResult | null = null; | |
| if (token) { | |
| // Bearer gateway auth wins when present; capability auth is only a fallback | |
| // for nodes that still own the route surface after bearer auth completes. | |
| const authResult = await authorizeHttpGatewayConnect({ | |
| auth: { ...auth, allowTailscale: false }, | |
| connectAuth: { token, password: token }, | |
| req, | |
| trustedProxies, | |
| allowRealIpFallback, | |
| rateLimiter, | |
| // The capability is part of this request's terminal credential set. A | |
| // stale bearer must not poison the shared bucket when the fallback wins. | |
| deferRateLimitFailure: Boolean(capability), | |
| browserOriginPolicy: resolveHttpBrowserOriginPolicy(req), | |
| }); | |
| if (authResult.ok) { | |
| return authResult; | |
| } | |
| lastAuthFailure = authResult; | |
| } | |
| if ( | |
| capability && | |
| hasAuthorizedPluginNodeCapability({ clients, surface: nodeCapability, capability }) | |
| ) { | |
| return { ok: true }; | |
| } | |
| if ( | |
| capability && | |
| (lastAuthFailure?.reason === "token_mismatch" || | |
| lastAuthFailure?.reason === "password_mismatch") | |
| ) { | |
| await rateLimiter?.recordFailureAndDelay( | |
| attribution.rateLimit.subject.key, | |
| AUTH_RATE_LIMIT_SCOPE_SHARED_SECRET, | |
| ); | |
| } | |
| return lastAuthFailure ?? { ok: false, reason: "unauthorized" }; | |
| }; | |
| return token && capability && rateLimiter | |
| ? await withSerializedCredentialFallbackAttempt({ | |
| limiter: rateLimiter, | |
| ip: attribution.rateLimit.subject.key, | |
| run, | |
| }) | |
| : await run(); | |
| } | |