App-Strategy-Support
DL29 - App Strategy Support for wix-server-client
Written for AI agents. See Log Methodology Note below for details.
Background
The wix-server-client package currently only supports ApiKeyStrategy for server-side authentication. The Wix SDK also provides AppStrategy, designed for Wix Apps that authenticate using an appId/appSecret pair. There's already a commented-out AppStrategy usage in wix-client-service.ts.
The @wix/sdk AppStrategy accepts:
appId(required)appSecret(optional)publicKey(optional)- One of:
refreshToken,instanceId, oraccessToken(all optional)
Problem
- API Key is user-level access, not site/project-level.
ApiKeyStrategyauthenticates as the user's account, not scoped to a specific site or app. Moving toAppStrategywith appSecret provides site-level access, which is the correct scope. - Setup requires interactive credential entry. The current flow prompts the user for an API key during
npm create jayor the setup hook. By automating appSecret retrieval via the Dev Center API, the setup becomes fully transparent — no interactive step needed.
Design
Make the server-side auth strategy configurable: the config can provide either apiKeyStrategy or appStrategy (exactly one is required).
Config YAML
Current:
apiKeyStrategy:
apiKey: 'IST.xxx'
siteId: 'abc-123'
oauthStrategy:
clientId: 'def-456'
New (option A — apiKey, unchanged):
apiKeyStrategy:
apiKey: 'IST.xxx'
siteId: 'abc-123'
oauthStrategy:
clientId: 'def-456'
New (option B — appStrategy):
appStrategy:
appId: 'my-app-id'
appSecret: 'my-app-secret'
oauthStrategy:
clientId: 'def-456'
Config Types
export interface ApiKeyConfig {
apiKey: string;
siteId: string;
}
export interface AppConfig {
appId: string;
appSecret: string;
}
export interface OAuthConfig {
clientId: string;
}
export type ServerAuthConfig =
| { kind: 'apiKey'; apiKey: ApiKeyConfig }
| { kind: 'app'; app: AppConfig };
export interface WixConfig {
auth: ServerAuthConfig;
oauth: OAuthConfig;
}
Config Loader Changes (config-loader.ts)
- Accept either
apiKeyStrategyorappStrategyin the YAML (exactly one required) - Validate the chosen strategy's fields
- Return
WixConfigwith the discriminatedServerAuthConfig
Client Service Changes (wix-client-service.ts)
export function provideWixClientService(config: WixConfig) {
const auth =
config.auth.kind === 'apiKey'
? ApiKeyStrategy({
apiKey: config.auth.apiKey.apiKey,
siteId: config.auth.apiKey.siteId,
})
: AppStrategy({
appId: config.auth.app.appId,
appSecret: config.auth.app.appSecret,
});
const instance = createClient({ auth, modules: {} });
registerService(WIX_CLIENT_SERVICE, instance);
}
Setup Changes (setup.ts)
hasValidCredentialsrecognises both strategy shapes- After
wix initcreateswix.config.json, automatically fetch appSecret via Dev Center API - Write
.wix.yamlwithappStrategy— no interactive credential prompts needed - Fall back to manual entry only if the automated fetch fails
Init Changes (init.ts)
- The
oauthClientIdpassthrough to the client stays the same — both strategies still use OAuth on the client side
Questions
Should
appSecretbe required or optional in the config? The SDK allows it to be optional, but for server-side use it's typically needed.- Decision: Required — the server-side use-case needs it.
Do we need to support the optional
refreshToken/instanceId/accessTokenfields onAppStrategy?- Decision: Not in the initial version. Start with
appId+appSecretonly.
- Decision: Not in the initial version. Start with
Is
oauthStrategystill required when usingappStrategy?- Question for user: With
appStrategy, the appId is the clientId for OAuth. Should the config inferoauthStrategy.clientIdfromappStrategy.appId, or still require it explicitly?
- Question for user: With
Implementation Plan
Phase 1: Config types and loader
- Update
WixConfigand addAppConfig,ServerAuthConfigtypes inconfig-loader.ts - Update
loadConfig()to accept either strategy, validate accordingly - Return discriminated union in
WixConfig.auth
Phase 2: Client service
- Update
provideWixClientServiceto branch onconfig.auth.kind
Phase 3: Setup
- Update
hasValidCredentialsto recogniseappStrategyconfig shape - Update interactive setup to support the new strategy
Phase 4: Init
- Handle the case where
oauthStrategy.clientIdcomes fromappStrategy.appId(if we decide to infer)
Exploration Results
Validated: The appSecret can be retrieved automatically during setup using the Dev Center API.
Automated Setup Flow
Prerequisites: user runs npx @wix/cli@latest login (already part of setup) and npx @wix/cli@latest init (creates wix.config.json with appId).
Steps:
npx @wix/cli@latest token→ get access tokenGET https://manage.wix.com/apps-service/v1/apps/{appId}?withSecrets=truewith headers:Authorization: {token}X-XSRF-TOKEN: nocheckCookie: XSRF-TOKEN=nocheck
- Response:
{ app: { appSecrets: { appSecret: "...", webhookPublicKey: "..." } } }
This means the interactive setup can be fully automated for appStrategy — no manual credential entry needed. The appId comes from wix.config.json, the appSecret from the Dev Center API, and the oauthStrategy.clientId is the same appId.
What didn't work
- BaaS env variables API (
/v2/app-projects/{appId}/app-environment-variables/environment/production) returned 404 — not usable for this purpose.
See exploration/wix-app-secret/ for the validation script.
Trade-offs
- Discriminated union vs. optional fields: Discriminated union (
kindfield) is more type-safe and makes the branching explicit. Slightly more verbose in the config loader, but prevents impossible states. - Keeping oauthStrategy separate vs. inferring from appId: Inferring reduces config boilerplate for
appStrategyusers, but introduces an implicit relationship. Explicit keeps things predictable.
Log Methodology Note
Note: These design logs are written primarily for AI agents as part of the Design Log methodology and made accessible here for human readers. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation.