From e27ed4449ae3cac0155852fe1cd7fd80c4d63298 Mon Sep 17 00:00:00 2001 From: Alex Montague Date: Mon, 10 Nov 2025 16:56:30 -0500 Subject: [PATCH 1/2] skip current identity uptime check --- packages/cli-kit/src/public/node/context/fqdn.ts | 3 +++ .../src/public/node/vendor/dev_server/network/host.ts | 6 ------ .../src/public/node/vendor/dev_server/network/index.ts | 6 +----- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/cli-kit/src/public/node/context/fqdn.ts b/packages/cli-kit/src/public/node/context/fqdn.ts index 483372e5135..b03b757d576 100644 --- a/packages/cli-kit/src/public/node/context/fqdn.ts +++ b/packages/cli-kit/src/public/node/context/fqdn.ts @@ -2,6 +2,7 @@ import {AbortError, BugError} from '../error.js' import {serviceEnvironment} from '../../../private/node/context/service.js' import {DevServer, DevServerCore} from '../vendor/dev_server/index.js' import {blockPartnersAccess} from '../environment.js' +import {setAssertRunning} from '../vendor/dev_server/dev-server-2024.js' export const NotProvidedStoreFQDNError = new AbortError( "Couldn't obtain the Shopify FQDN because the store FQDN was not provided.", @@ -115,6 +116,8 @@ export async function identityFqdn(): Promise { const productionFqdn = 'accounts.shopify.com' switch (environment) { case 'local': + // force identity uptime check to pass + setAssertRunning((projectName) => projectName === 'identity') return new DevServer('identity').host() default: return productionFqdn diff --git a/packages/cli-kit/src/public/node/vendor/dev_server/network/host.ts b/packages/cli-kit/src/public/node/vendor/dev_server/network/host.ts index 6580f94c4da..d1aa2749fb7 100644 --- a/packages/cli-kit/src/public/node/vendor/dev_server/network/host.ts +++ b/packages/cli-kit/src/public/node/vendor/dev_server/network/host.ts @@ -48,9 +48,3 @@ export function getIpFromHosts(hostname: string) { throw new Error(`No IP found for hostname: ${hostname}`) } - -// eslint-disable-next-line @typescript-eslint/naming-convention -export function TEST_ClearCache() { - hostToIpCache = {} - lastModifiedTime = 0 -} diff --git a/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts b/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts index 6bfcf79ea0e..5871c34a5ae 100644 --- a/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts +++ b/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts @@ -18,6 +18,7 @@ let checkPort: ReturnType export function assertConnectable(options: ConnectionArguments): void { checkPort ||= getCheckPortHelper() + debugger const {port, addr, timeout = DEFAULT_CONNECT_TIMEOUT} = options try { @@ -33,11 +34,6 @@ export function assertConnectable(options: ConnectionArguments): void { } } -// eslint-disable-next-line @typescript-eslint/naming-convention -export function TEST_testResetCheckPort(): void { - checkPort = getCheckPortHelper() -} - function getCheckPortHelper(): (addr: string, port: number, timeout: number) => boolean { return fallbackCheckPort } From 7f09479a59a2e58946d8cf389168cf4562f6b2cd Mon Sep 17 00:00:00 2001 From: Alex Montague Date: Tue, 11 Nov 2025 11:24:31 -0500 Subject: [PATCH 2/2] attempt to fetch mock user from identity endpoint --- packages/cli-kit/src/private/node/session.ts | 11 ++ .../src/private/node/session/mock-auth.ts | 112 ++++++++++++++++++ .../node/vendor/dev_server/network/index.ts | 2 +- 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 packages/cli-kit/src/private/node/session/mock-auth.ts diff --git a/packages/cli-kit/src/private/node/session.ts b/packages/cli-kit/src/private/node/session.ts index 41409c83e69..616c95155b9 100644 --- a/packages/cli-kit/src/private/node/session.ts +++ b/packages/cli-kit/src/private/node/session.ts @@ -12,6 +12,7 @@ import { import {IdentityToken, Session, Sessions} from './session/schema.js' import * as sessionStore from './session/store.js' import {pollForDeviceAuthorization, requestDeviceAuthorization} from './session/device-authorization.js' +import {shouldUseMockAuth, fetchMockUser, buildMockSession} from './session/mock-auth.js' import {isThemeAccessSession} from './api/rest.js' import {getCurrentSessionId, setCurrentSessionId} from './conf-store.js' import {UserEmailQueryString, UserEmailQuery} from './api/graphql/business-platform-destinations/user-email.js' @@ -197,6 +198,7 @@ export async function ensureAuthenticated( {forceRefresh = false, noPrompt = false, forceNewSession = false}: EnsureAuthenticatedAdditionalOptions = {}, ): Promise { const fqdn = await identityFqdn() + // debugger const previousStoreFqdn = applications.adminApi?.storeFqdn if (previousStoreFqdn) { @@ -301,6 +303,15 @@ async function executeCompleteFlow(applications: OAuthApplications): Promise { + const devDashboardFqdn = await developerDashboardFqdn() + const scopeParam = scopes.join(' ') + const nonce = Math.random().toString(36).substring(2) + const state = Math.random().toString(36).substring(2) + + const params = new URLSearchParams({ + 'config-key': 'cli', + scope: scopeParam, + nonce, + state, + 'created-at': Date.now().toString(), + }) + + const url = `https://${devDashboardFqdn}/identity/test-login?${params.toString()}` + + outputDebug(outputContent`Fetching mock user from: ${url}`) + + const response = await shopifyFetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + }, + }) + + if (!response.ok) { + const text = await response.text() + outputDebug(outputContent`Failed response: ${text.substring(0, 500)}`) + throw new Error(`Failed to fetch mock user: ${response.status} ${response.statusText}`) + } + + const data = (await response.json()) as MockUserResponse + outputDebug(outputContent`Mock user fetched: ${outputToken.json(data)}`) + + return data +} + +export function buildMockIdentityToken(mockUser: MockUserResponse, scopes: string[]): IdentityToken { + const expiresAt = new Date(mockUser.expires_at) + + return { + accessToken: mockUser.access_token, + refreshToken: mockUser.refresh_token, + expiresAt, + scopes, + userId: mockUser.uuid, + } +} + +export function buildMockSession(mockUser: MockUserResponse, scopes: string[]): Session { + const identityToken = buildMockIdentityToken(mockUser, scopes) + + return { + identity: { + ...identityToken, + alias: mockUser.userinfo.email, + }, + applications: {}, + } +} diff --git a/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts b/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts index 5871c34a5ae..5c440dfdca0 100644 --- a/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts +++ b/packages/cli-kit/src/public/node/vendor/dev_server/network/index.ts @@ -18,7 +18,7 @@ let checkPort: ReturnType export function assertConnectable(options: ConnectionArguments): void { checkPort ||= getCheckPortHelper() - debugger + // debugger const {port, addr, timeout = DEFAULT_CONNECT_TIMEOUT} = options try {