Files
openclaw/apps/shared/OpenClawKit/Sources/OpenClawKit/DeviceAuthPayload.swift
2026-03-02 12:13:45 +00:00

77 lines
2.5 KiB
Swift

import Foundation
import OpenClawProtocol
public enum GatewayDeviceAuthPayload {
public static func buildV3(
deviceId: String,
clientId: String,
clientMode: String,
role: String,
scopes: [String],
signedAtMs: Int,
token: String?,
nonce: String,
platform: String?,
deviceFamily: String?) -> String
{
let scopeString = scopes.joined(separator: ",")
let authToken = token ?? ""
let normalizedPlatform = normalizeMetadataField(platform)
let normalizedDeviceFamily = normalizeMetadataField(deviceFamily)
return [
"v3",
deviceId,
clientId,
clientMode,
role,
scopeString,
String(signedAtMs),
authToken,
nonce,
normalizedPlatform,
normalizedDeviceFamily,
].joined(separator: "|")
}
static func normalizeMetadataField(_ value: String?) -> String {
guard let value else { return "" }
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty {
return ""
}
// Keep cross-runtime normalization deterministic (TS/Swift/Kotlin):
// lowercase ASCII A-Z only for auth payload metadata fields.
var output = String()
output.reserveCapacity(trimmed.count)
for scalar in trimmed.unicodeScalars {
let codePoint = scalar.value
if codePoint >= 65, codePoint <= 90, let lowered = UnicodeScalar(codePoint + 32) {
output.unicodeScalars.append(lowered)
} else {
output.unicodeScalars.append(scalar)
}
}
return output
}
public static func signedDeviceDictionary(
payload: String,
identity: DeviceIdentity,
signedAtMs: Int,
nonce: String) -> [String: OpenClawProtocol.AnyCodable]?
{
guard let signature = DeviceIdentityStore.signPayload(payload, identity: identity),
let publicKey = DeviceIdentityStore.publicKeyBase64Url(identity)
else {
return nil
}
return [
"id": OpenClawProtocol.AnyCodable(identity.deviceId),
"publicKey": OpenClawProtocol.AnyCodable(publicKey),
"signature": OpenClawProtocol.AnyCodable(signature),
"signedAt": OpenClawProtocol.AnyCodable(signedAtMs),
"nonce": OpenClawProtocol.AnyCodable(nonce),
]
}
}