




















@@ -89,6 +89,14 @@ type StoredDeviceAuth = {
8989scopes?: string[];
9090};
919192+type AssembledConnect = {
93+params: ConnectParams;
94+authApprovalRuntimeToken: string | undefined;
95+resolvedDeviceToken: string | undefined;
96+storedToken: string | undefined;
97+usingStoredDeviceToken: boolean | undefined;
98+};
99+92100type FingerprintCheckingClientOptions = Omit<ClientOptions, "checkServerIdentity"> & {
93101checkServerIdentity?: (servername: string, cert: CertMeta) => Error | undefined;
94102};
@@ -538,100 +546,9 @@ export class GatewayClient {
538546return;
539547}
540548const role = this.opts.role ?? "operator";
541-let authApprovalRuntimeToken: string | undefined;
542-let resolvedDeviceToken: string | undefined;
543-let storedToken: string | undefined;
544-let usingStoredDeviceToken: boolean | undefined;
545-let params: ConnectParams;
549+let assembled: AssembledConnect;
546550try {
547-const {
548- authToken,
549- authBootstrapToken,
550- authDeviceToken,
551- authPassword,
552-authApprovalRuntimeToken: selectedAuthApprovalRuntimeToken,
553- signatureToken,
554-resolvedDeviceToken: selectedResolvedDeviceToken,
555-storedToken: selectedStoredToken,
556- storedScopes,
557-usingStoredDeviceToken: selectedUsingStoredDeviceToken,
558-} = this.selectConnectAuth(role);
559-authApprovalRuntimeToken = selectedAuthApprovalRuntimeToken;
560-resolvedDeviceToken = selectedResolvedDeviceToken;
561-storedToken = selectedStoredToken;
562-usingStoredDeviceToken = selectedUsingStoredDeviceToken;
563-if (this.pendingDeviceTokenRetry && authDeviceToken) {
564-this.pendingDeviceTokenRetry = false;
565-}
566-const auth =
567-authToken ||
568-authBootstrapToken ||
569-authPassword ||
570-resolvedDeviceToken ||
571-authApprovalRuntimeToken
572- ? {
573-token: authToken,
574-bootstrapToken: authBootstrapToken,
575-deviceToken: authDeviceToken ?? resolvedDeviceToken,
576-password: authPassword,
577-approvalRuntimeToken: authApprovalRuntimeToken,
578-}
579- : undefined;
580-const signedAtMs = Date.now();
581-const scopes = this.resolveConnectScopes({
582- usingStoredDeviceToken,
583- storedScopes,
584-});
585-const platform = this.opts.platform ?? process.platform;
586-const device = (() => {
587-if (!this.opts.deviceIdentity) {
588-return undefined;
589-}
590-const payload = buildDeviceAuthPayloadV3({
591-deviceId: this.opts.deviceIdentity.deviceId,
592-clientId: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
593-clientMode: this.opts.mode ?? GATEWAY_CLIENT_MODES.BACKEND,
594- role,
595- scopes,
596- signedAtMs,
597-token: signatureToken ?? null,
598- nonce,
599- platform,
600-deviceFamily: this.opts.deviceFamily,
601-});
602-const signature = signDevicePayload(this.opts.deviceIdentity.privateKeyPem, payload);
603-return {
604-id: this.opts.deviceIdentity.deviceId,
605-publicKey: publicKeyRawBase64UrlFromPem(this.opts.deviceIdentity.publicKeyPem),
606- signature,
607-signedAt: signedAtMs,
608- nonce,
609-};
610-})();
611-params = {
612-minProtocol: this.opts.minProtocol ?? MIN_CLIENT_PROTOCOL_VERSION,
613-maxProtocol: this.opts.maxProtocol ?? PROTOCOL_VERSION,
614-client: {
615-id: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
616-displayName: this.opts.clientDisplayName,
617-version: this.opts.clientVersion ?? VERSION,
618- platform,
619-deviceFamily: this.opts.deviceFamily,
620-mode: this.opts.mode ?? GATEWAY_CLIENT_MODES.BACKEND,
621-instanceId: this.opts.instanceId,
622-},
623-caps: Array.isArray(this.opts.caps) ? this.opts.caps : [],
624-commands: Array.isArray(this.opts.commands) ? this.opts.commands : undefined,
625-permissions:
626-this.opts.permissions && typeof this.opts.permissions === "object"
627- ? this.opts.permissions
628- : undefined,
629-pathEnv: this.opts.pathEnv,
630- auth,
631- role,
632- scopes,
633- device,
634-};
551+assembled = this.assembleConnectParams({ role, nonce });
635552} catch (err) {
636553this.handleConnectFailure(err);
637554return;
@@ -640,7 +557,7 @@ export class GatewayClient {
640557this.connectSent = true;
641558this.clearConnectChallengeTimeout();
642559643-void this.request<HelloOk>("connect", params)
560+void this.request<HelloOk>("connect", assembled.params)
644561.then((helloOk) => {
645562this.pendingDeviceTokenRetry = false;
646563this.deviceTokenRetryBudgetUsed = false;
@@ -674,12 +591,12 @@ export class GatewayClient {
674591const shouldRetryWithDeviceToken = this.shouldRetryWithStoredDeviceToken({
675592error: err,
676593explicitGatewayToken: normalizeOptionalString(this.opts.token),
677- resolvedDeviceToken,
678-storedToken: storedToken ?? undefined,
594+resolvedDeviceToken: assembled.resolvedDeviceToken,
595+storedToken: assembled.storedToken,
679596});
680597if (
681598this.opts.deviceIdentity &&
682-usingStoredDeviceToken &&
599+assembled.usingStoredDeviceToken &&
683600err instanceof GatewayClientRequestError &&
684601readConnectErrorDetailCode(err.details) ===
685602ConnectErrorDetailCodes.AUTH_DEVICE_TOKEN_MISMATCH
@@ -709,7 +626,7 @@ export class GatewayClient {
709626if (
710627this.shouldRetryWithoutApprovalRuntimeToken({
711628error: err,
712- authApprovalRuntimeToken,
629+authApprovalRuntimeToken: assembled.authApprovalRuntimeToken,
713630})
714631) {
715632this.approvalRuntimeTokenCompatibilityDisabled = true;
@@ -730,6 +647,120 @@ export class GatewayClient {
730647});
731648}
732649650+private assembleConnectParams(params: { role: string; nonce: string }): AssembledConnect {
651+const { role, nonce } = params;
652+const selectedAuth = this.selectConnectAuth(role);
653+const {
654+ authToken,
655+ authBootstrapToken,
656+ authDeviceToken,
657+ authPassword,
658+ authApprovalRuntimeToken,
659+ signatureToken,
660+ resolvedDeviceToken,
661+ storedToken,
662+ storedScopes,
663+ usingStoredDeviceToken,
664+} = selectedAuth;
665+666+if (this.pendingDeviceTokenRetry && authDeviceToken) {
667+this.pendingDeviceTokenRetry = false;
668+}
669+670+const auth =
671+authToken ||
672+authBootstrapToken ||
673+authPassword ||
674+resolvedDeviceToken ||
675+authApprovalRuntimeToken
676+ ? {
677+token: authToken,
678+bootstrapToken: authBootstrapToken,
679+deviceToken: authDeviceToken ?? resolvedDeviceToken,
680+password: authPassword,
681+approvalRuntimeToken: authApprovalRuntimeToken,
682+}
683+ : undefined;
684+const signedAtMs = Date.now();
685+const scopes = this.resolveConnectScopes({
686+ usingStoredDeviceToken,
687+ storedScopes,
688+});
689+const platform = this.opts.platform ?? process.platform;
690+691+return {
692+params: {
693+minProtocol: this.opts.minProtocol ?? MIN_CLIENT_PROTOCOL_VERSION,
694+maxProtocol: this.opts.maxProtocol ?? PROTOCOL_VERSION,
695+client: {
696+id: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
697+displayName: this.opts.clientDisplayName,
698+version: this.opts.clientVersion ?? VERSION,
699+ platform,
700+deviceFamily: this.opts.deviceFamily,
701+mode: this.opts.mode ?? GATEWAY_CLIENT_MODES.BACKEND,
702+instanceId: this.opts.instanceId,
703+},
704+caps: Array.isArray(this.opts.caps) ? this.opts.caps : [],
705+commands: Array.isArray(this.opts.commands) ? this.opts.commands : undefined,
706+permissions:
707+this.opts.permissions && typeof this.opts.permissions === "object"
708+ ? this.opts.permissions
709+ : undefined,
710+pathEnv: this.opts.pathEnv,
711+ auth,
712+ role,
713+ scopes,
714+device: this.buildDeviceConnectParams({
715+ nonce,
716+ role,
717+ scopes,
718+ signatureToken,
719+ signedAtMs,
720+ platform,
721+}),
722+},
723+ authApprovalRuntimeToken,
724+ resolvedDeviceToken,
725+ storedToken,
726+ usingStoredDeviceToken,
727+};
728+}
729+730+private buildDeviceConnectParams(params: {
731+nonce: string;
732+role: string;
733+scopes: string[];
734+signatureToken: string | undefined;
735+signedAtMs: number;
736+platform: string;
737+}): ConnectParams["device"] {
738+if (!this.opts.deviceIdentity) {
739+return undefined;
740+}
741+const { nonce, role, scopes, signatureToken, signedAtMs, platform } = params;
742+const payload = buildDeviceAuthPayloadV3({
743+deviceId: this.opts.deviceIdentity.deviceId,
744+clientId: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
745+clientMode: this.opts.mode ?? GATEWAY_CLIENT_MODES.BACKEND,
746+ role,
747+ scopes,
748+ signedAtMs,
749+token: signatureToken ?? null,
750+ nonce,
751+ platform,
752+deviceFamily: this.opts.deviceFamily,
753+});
754+const signature = signDevicePayload(this.opts.deviceIdentity.privateKeyPem, payload);
755+return {
756+id: this.opts.deviceIdentity.deviceId,
757+publicKey: publicKeyRawBase64UrlFromPem(this.opts.deviceIdentity.publicKeyPem),
758+ signature,
759+signedAt: signedAtMs,
760+ nonce,
761+};
762+}
763+733764private handleConnectFailure(err: unknown) {
734765const error = err instanceof Error ? err : new Error(String(err));
735766this.clearConnectChallengeTimeout();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。