Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/heavy-adults-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@shopify/cli-kit': minor
'@shopify/app': minor
---

Add support for SHOPIFY_CLI_TOKEN env var as a new name for SHOPIFY_CLI_PARTNERS_TOKEN
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ import {
AppLogsSubscribeMutationVariables,
} from '../../api/graphql/app-management/generated/app-logs-subscribe.js'
import {SourceExtension} from '../../api/graphql/app-management/generated/types.js'
import {getPartnersToken} from '@shopify/cli-kit/node/environment'
import {getCliToken} from '@shopify/cli-kit/node/environment'
import {ensureAuthenticatedAppManagementAndBusinessPlatform, Session} from '@shopify/cli-kit/node/session'
import {isUnitTest} from '@shopify/cli-kit/node/context/local'
import {AbortError, BugError} from '@shopify/cli-kit/node/error'
Expand Down Expand Up @@ -294,7 +294,7 @@ export class AppManagementClient implements DeveloperPlatformClient {
unauthorizedHandler: this.createUnauthorizedHandler('businessPlatform'),
})

if (getPartnersToken() && userInfoResult.currentUserAccount) {
if (getCliToken() && userInfoResult.currentUserAccount) {
const organizations = userInfoResult.currentUserAccount.organizations.nodes.map((org) => ({
name: org.name,
}))
Expand Down
1 change: 1 addition & 0 deletions packages/cli-kit/src/private/node/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const environmentVariables = {
env: 'SHOPIFY_CLI_ENV',
firstPartyDev: 'SHOPIFY_CLI_1P_DEV',
noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',
cliToken: 'SHOPIFY_CLI_TOKEN',
partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',
runAsUser: 'SHOPIFY_RUN_AS_USER',
serviceEnv: 'SHOPIFY_SERVICE_ENV',
Expand Down
10 changes: 5 additions & 5 deletions packages/cli-kit/src/private/node/session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import * as fqdnModule from '../../public/node/context/fqdn.js'
import {themeToken} from '../../public/node/context/local.js'
import {partnersRequest} from '../../public/node/api/partners.js'
import {businessPlatformRequest} from '../../public/node/api/business-platform.js'
import {getPartnersToken} from '../../public/node/environment.js'
import {getCliToken} from '../../public/node/environment.js'
import {nonRandomUUID} from '../../public/node/crypto.js'
import {terminalSupportsPrompting} from '../../public/node/system.js'

Expand Down Expand Up @@ -319,7 +319,7 @@ describe('when existing session is valid', () => {
// Given
vi.mocked(validateSession).mockResolvedValueOnce('ok')
vi.mocked(fetchSessions).mockResolvedValue(validSessions)
vi.mocked(getPartnersToken).mockReturnValue('custom_cli_token')
vi.mocked(getCliToken).mockReturnValue('custom_cli_token')
const expected = {...validTokens, partners: 'custom_partners_token'}

// When
Expand Down Expand Up @@ -450,7 +450,7 @@ describe('getLastSeenUserIdAfterAuth', () => {
test('returns UUID based on partners token if present in environment', async () => {
// Given
vi.mocked(getCurrentSessionId).mockReturnValue(undefined)
vi.mocked(getPartnersToken).mockReturnValue('partners-token-456')
vi.mocked(getCliToken).mockReturnValue('partners-token-456')

// When
const userId = await getLastSeenUserIdAfterAuth()
Expand Down Expand Up @@ -540,7 +540,7 @@ describe('setLastSeenUserIdAfterAuth', () => {
describe('getLastSeenAuthMethod', () => {
beforeEach(() => {
vi.mocked(getCurrentSessionId).mockReturnValue(undefined)
vi.mocked(getPartnersToken).mockReturnValue(undefined)
vi.mocked(getCliToken).mockReturnValue(undefined)
vi.mocked(themeToken).mockReturnValue(undefined)
setLastSeenAuthMethod('none')
})
Expand Down Expand Up @@ -571,7 +571,7 @@ describe('getLastSeenAuthMethod', () => {

test('returns partners_token if there is a partners token in the environment', async () => {
// Given
vi.mocked(getPartnersToken).mockReturnValue('partners-token-456')
vi.mocked(getCliToken).mockReturnValue('partners-token-456')

// When
const method = await getLastSeenAuthMethod()
Expand Down
8 changes: 4 additions & 4 deletions packages/cli-kit/src/private/node/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {outputContent, outputToken, outputDebug, outputCompleted} from '../../pu
import {firstPartyDev, themeToken} from '../../public/node/context/local.js'
import {AbortError} from '../../public/node/error.js'
import {normalizeStoreFqdn, identityFqdn} from '../../public/node/context/fqdn.js'
import {getIdentityTokenInformation, getPartnersToken} from '../../public/node/environment.js'
import {getIdentityTokenInformation, getCliToken} from '../../public/node/environment.js'
import {AdminSession, logout} from '../../public/node/session.js'
import {nonRandomUUID} from '../../public/node/crypto.js'
import {isEmpty} from '../../public/common/object.js'
Expand Down Expand Up @@ -137,7 +137,7 @@ export async function getLastSeenUserIdAfterAuth(): Promise<string> {
const currentSessionId = getCurrentSessionId()
if (currentSessionId) return currentSessionId

const customToken = getPartnersToken() ?? themeToken()
const customToken = getCliToken() ?? themeToken()
return customToken ? nonRandomUUID(customToken) : 'unknown'
}

Expand All @@ -162,7 +162,7 @@ export async function getLastSeenAuthMethod(): Promise<AuthMethod> {

if (getCurrentSessionId()) return 'device_auth'

const partnersToken = getPartnersToken()
const partnersToken = getCliToken()
if (partnersToken) return 'partners_token'

const themePassword = themeToken()
Expand Down Expand Up @@ -264,7 +264,7 @@ ${outputToken.json(applications)}
const tokens = await tokensFor(applications, completeSession)

// Overwrite partners token if using a custom CLI Token
const envToken = getPartnersToken()
const envToken = getCliToken()
if (envToken && applications.partnersApi) {
tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken
}
Expand Down
16 changes: 8 additions & 8 deletions packages/cli-kit/src/private/node/session/exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ export async function refreshAccessToken(currentToken: IdentityToken): Promise<I
}

/**
* Given a custom CLI token passed as ENV variable request a valid API access token
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
* Given a custom CLI token passed as ENV variable, request a valid API access token.
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
* @param apiName - The API to exchange for the access token
* @param scopes - The scopes to request with the access token
* @returns An instance with the application access tokens.
Expand Down Expand Up @@ -100,18 +100,18 @@ async function exchangeCliTokenForAccessToken(
}

/**
* Given a custom CLI token passed as ENV variable, request a valid Partners API token
* Given a custom CLI token passed as ENV variable, request a valid Partners API token.
* This token does not accept extra scopes, just the cli one.
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
* @returns An instance with the application access tokens.
*/
export async function exchangeCustomPartnerToken(token: string): Promise<{accessToken: string; userId: string}> {
return exchangeCliTokenForAccessToken('partners', token, tokenExchangeScopes('partners'))
}

/**
* Given a custom CLI token passed as ENV variable, request a valid App Management API token
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
* Given a custom CLI token passed as ENV variable, request a valid App Management API token.
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
* @returns An instance with the application access tokens.
*/
export async function exchangeCliTokenForAppManagementAccessToken(
Expand All @@ -121,8 +121,8 @@ export async function exchangeCliTokenForAppManagementAccessToken(
}

/**
* Given a custom CLI token passed as ENV variable, request a valid Business Platform API token
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
* Given a custom CLI token passed as ENV variable, request a valid Business Platform API token.
* @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
* @returns An instance with the application access tokens.
*/
export async function exchangeCliTokenForBusinessPlatformAccessToken(
Expand Down
33 changes: 33 additions & 0 deletions packages/cli-kit/src/public/node/environment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {getCliToken} from './environment.js'
import {environmentVariables} from '../../private/node/constants.js'
import {describe, expect, test, beforeEach} from 'vitest'

beforeEach(() => {
delete process.env[environmentVariables.cliToken]
delete process.env[environmentVariables.partnersToken]
})

describe('getCliToken', () => {
test('returns SHOPIFY_CLI_TOKEN when set', () => {
process.env[environmentVariables.cliToken] = 'new-token'

expect(getCliToken()).toBe('new-token')
})

test('returns SHOPIFY_CLI_PARTNERS_TOKEN when SHOPIFY_CLI_TOKEN is not set', () => {
process.env[environmentVariables.partnersToken] = 'old-token'

expect(getCliToken()).toBe('old-token')
})

test('prefers SHOPIFY_CLI_TOKEN over SHOPIFY_CLI_PARTNERS_TOKEN', () => {
process.env[environmentVariables.cliToken] = 'new-token'
process.env[environmentVariables.partnersToken] = 'old-token'

expect(getCliToken()).toBe('new-token')
})

test('returns undefined when neither env var is set', () => {
expect(getCliToken()).toBeUndefined()
})
})
19 changes: 6 additions & 13 deletions packages/cli-kit/src/public/node/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,14 @@ export function getEnvironmentVariables(): NodeJS.ProcessEnv {
}

/**
* Returns the value of the SHOPIFY_CLI_PARTNERS_TOKEN environment variable.
* Returns the value of the SHOPIFY_CLI_TOKEN environment variable,
* falling back to the deprecated SHOPIFY_CLI_PARTNERS_TOKEN.
*
* @returns Current process environment variables.
*/
export function getPartnersToken(): string | undefined {
return getEnvironmentVariables()[environmentVariables.partnersToken]
}

/**
* Check if the current proccess is running using the partners token.
*
* @returns True if the current proccess is running using the partners token.
* @returns The CLI token value, or undefined if neither env var is set.
*/
export function usePartnersToken(): boolean {
return getPartnersToken() !== undefined
export function getCliToken(): string | undefined {
const env = getEnvironmentVariables()
return env[environmentVariables.cliToken] ?? env[environmentVariables.partnersToken]
}

/**
Expand Down
6 changes: 3 additions & 3 deletions packages/cli-kit/src/public/node/session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ensureAuthenticatedThemes,
} from './session.js'

import {getPartnersToken} from './environment.js'
import {getCliToken} from './environment.js'
import {shopifyFetch} from './http.js'
import {ApplicationToken} from '../../private/node/session/schema.js'
import {ensureAuthenticated, setLastSeenAuthMethod, setLastSeenUserIdAfterAuth} from '../../private/node/session.js'
Expand Down Expand Up @@ -136,7 +136,7 @@ describe('ensureAuthenticatedPartners', () => {
accessToken: partnersToken.accessToken,
userId: '575e2102-cb13-7bea-4631-ce3469eac491cdcba07d',
})
vi.mocked(getPartnersToken).mockReturnValue('custom_cli_token')
vi.mocked(getCliToken).mockReturnValue('custom_cli_token')

// When
const got = await ensureAuthenticatedPartners([])
Expand Down Expand Up @@ -253,7 +253,7 @@ describe('ensureAuthenticatedAppManagementAndBusinessPlatform', () => {

test('returns app managment and business platform tokens if CLI token envvar is defined', async () => {
// Given
vi.mocked(getPartnersToken).mockReturnValue('custom_cli_token')
vi.mocked(getCliToken).mockReturnValue('custom_cli_token')
vi.mocked(exchangeCliTokenForAppManagementAccessToken).mockResolvedValueOnce({
accessToken: 'app-management-token',
userId: '575e2102-cb13-7bea-4631-ce3469eac491cdcba07d',
Expand Down
6 changes: 3 additions & 3 deletions packages/cli-kit/src/public/node/session.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {shopifyFetch} from './http.js'
import {nonRandomUUID} from './crypto.js'
import {getPartnersToken} from './environment.js'
import {getCliToken} from './environment.js'
import {AbortError, BugError} from './error.js'
import {outputContent, outputToken, outputDebug} from './output.js'
import * as sessionStore from '../../private/node/session/store.js'
Expand Down Expand Up @@ -110,7 +110,7 @@ export async function ensureAuthenticatedPartners(
outputDebug(outputContent`Ensuring that the user is authenticated with the Partners API with the following scopes:
${outputToken.json(scopes)}
`)
const envToken = getPartnersToken()
const envToken = getCliToken()
if (envToken) {
const result = await exchangeCustomPartnerToken(envToken)
return {token: result.accessToken, userId: result.userId}
Expand Down Expand Up @@ -141,7 +141,7 @@ export async function ensureAuthenticatedAppManagementAndBusinessPlatform(
${outputToken.json(appManagementScopes)}
`)

const envToken = getPartnersToken()
const envToken = getCliToken()
if (envToken) {
const appManagmentToken = await exchangeCliTokenForAppManagementAccessToken(envToken)
const businessPlatformToken = await exchangeCliTokenForBusinessPlatformAccessToken(envToken)
Expand Down
Loading