OAuth renderer does not support credentials inside array items
Problem
The UI OAuth renderer assumes credentials live at a fixed top-level path in the endpoint config. When a connector schema places credentials inside array items (e.g. a stores array where each item has its own credentials object), the OAuth flow breaks because:
- The Mustache templates in the connector's OAuth2Spec reference fields like
{{{ config.store }}}, but the actual value lives at config.stores[N].store -- the backend cannot resolve it.
- The
authURL and accessToken API calls send the raw endpoint config, which has no top-level store field for the template to bind to.
The OAuth renderer already handles being rendered inside an array (it detects array paths via isInsideArray and writes tokens back to the correct index via handleChange), but the config sent to the backend for template rendering is not adjusted.
Impact
Any connector whose schema uses an array of items with per-item OAuth credentials will hit this. The immediate case is the Shopify source connector, which is migrating to a multi-store array model. Once the OAuth app is approved and the connector ships the multi-store update, users will not be able to authenticate individual stores through the UI.
Proposal
Introduce a Virtual Config Flattening step in useOauthHandler that intercepts the config before it is sent to the backend. When the OAuth renderer detects it is inside an array item (via the JSONForms path prop), it:
- Extracts the array field name and index from the path (e.g.
stores.2.credentials -> array stores, index 2)
- Reads the current array item from the endpoint config
- Promotes scalar fields from that item to the top level of a shallow config copy
- Sends this virtual config to
authURL() and accessToken() instead of the raw config
Non-array OAuth flows are unaffected -- when the path has no array index the original config passes through unchanged.
Scope
- ~50 lines of new code across 3 modified files + 1 new utility module
- 2 new test files (28 tests)
- Zero changes to backend, protocol, CDK, or connector code
- No breaking changes to existing OAuth connectors
Key files
ui/src/forms/shared.ts -- new getArrayContext() utility
ui/src/forms/renderers/OAuth/buildVirtualConfig.ts -- new module, pure function
ui/src/forms/renderers/OAuth/useOauthHandler.ts -- accepts credentialsPath, uses virtual config
ui/src/forms/renderers/OAuth/index.tsx -- passes path to handler
References
OAuth renderer does not support credentials inside array items
Problem
The UI OAuth renderer assumes credentials live at a fixed top-level path in the endpoint config. When a connector schema places credentials inside array items (e.g. a
storesarray where each item has its owncredentialsobject), the OAuth flow breaks because:{{{ config.store }}}, but the actual value lives atconfig.stores[N].store-- the backend cannot resolve it.authURLandaccessTokenAPI calls send the raw endpoint config, which has no top-levelstorefield for the template to bind to.The OAuth renderer already handles being rendered inside an array (it detects array paths via
isInsideArrayand writes tokens back to the correct index viahandleChange), but the config sent to the backend for template rendering is not adjusted.Impact
Any connector whose schema uses an array of items with per-item OAuth credentials will hit this. The immediate case is the Shopify source connector, which is migrating to a multi-store array model. Once the OAuth app is approved and the connector ships the multi-store update, users will not be able to authenticate individual stores through the UI.
Proposal
Introduce a Virtual Config Flattening step in
useOauthHandlerthat intercepts the config before it is sent to the backend. When the OAuth renderer detects it is inside an array item (via the JSONFormspathprop), it:stores.2.credentials-> arraystores, index2)authURL()andaccessToken()instead of the raw configNon-array OAuth flows are unaffected -- when the path has no array index the original config passes through unchanged.
Scope
Key files
ui/src/forms/shared.ts-- newgetArrayContext()utilityui/src/forms/renderers/OAuth/buildVirtualConfig.ts-- new module, pure functionui/src/forms/renderers/OAuth/useOauthHandler.ts-- acceptscredentialsPath, uses virtual configui/src/forms/renderers/OAuth/index.tsx-- passespathto handlerReferences