[Feature] Add token exchange auth strategy and hooks support to shopify-app-express#3097
[Feature] Add token exchange auth strategy and hooks support to shopify-app-express#3097mrmarufpro wants to merge 4 commits into
Conversation
|
I've been running these changes in a production embedded app by patching the package locally, and everything is working as expected. Token exchange flows complete cleanly, I did need a couple of minor tweaks to get it wired up in my app, but nothing that points to a problem with the implementation itself — just the usual integration details. Overall the behavior is solid and consistent with how the Remix package handles token exchange. Happy to share more specifics if it helps the review. |
|
Hi @lizkenyon, I’m requesting a review. |
7cafd76 to
b15adad
Compare
f449547 to
65f1035
Compare
781885c to
0788067
Compare
|
May I ask if this is going to be released soon? We're now required to use expiring offline access tokens so there doesn't seem to be a way to cleanly use this library with new apps. |
Hi @dansundy, I’m also looking forward to the review. In the meantime, you can patch |
|
Thanks @mrmarufpro. Will do! |
|
hi! wen merge? |
|
Hi @kelreel, thanks for following up. The PR is currently awaiting review from the Shopify maintainers. If you'd like to use the feature before it's merged, you can apply the changes to your installed Let me know if you run into any issues, and I'll be glad to help. |
|
This feature is urgently needed for app developers. Why are critical platform changes being rolled out before the official libraries are ready? Сould you please review this and complete the feature @tobi @mkevinosullivan @byrichardpowell ? |
… support Implements the `unstable_newEmbeddedAuthStrategy` future flag which enables token exchange-based authentication for embedded apps, bypassing the OAuth redirect flow when a Bearer session token is present. Also adds: - `future` config option with feature flag support and logging - `hooks.afterAuth` callback invoked after OAuth and token exchange flows - `registerWebhooks` convenience method on the ShopifyApp object - `idempotentPromiseHandler` to deduplicate concurrent hook invocations - `expiring` offline access token support in auth callback and token exchange - `ensureOfflineTokenIsNotExpired` helper to refresh tokens nearing expiry Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ession invalidation - Extract session token helpers (header + URL param) into get-session-token.ts - Add respondToInvalidSessionToken helper with retry-header support - Add invalidateAccessToken helper to clear stale access tokens from storage - Send X-Shopify-Retry-Invalid-Session-Request:1 header on JWT/subject-token errors - Invalidate stored access token on Shopify 401 responses to force re-exchange - Fix URL parsing to use new URL().hostname instead of string replace - Update tests to assert retry header and access-token invalidation behaviour - Fix docs example to await shopify.registerWebhooks() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
WHY are these changes introduced?
Fixes #630, Fixes #3208 — adds token exchange authentication support to
shopify-app-express, bringing it to parity with the Remix package.Shopify's token exchange API reduces flickering and OAuth redirects for embedded apps. While this was already supported in the Remix package, Express apps had no way to use it. This PR implements token exchange for Express behind the
unstable_newEmbeddedAuthStrategyfuture flag so existing apps are unaffected.WHAT is this pull request doing?
futureconfig option — adds a feature flag system (unstable_newEmbeddedAuthStrategy,expiringOfflineAccessTokens) with logging for disabled flagsperform-token-exchange.ts) — whenunstable_newEmbeddedAuthStrategyis enabled and a Bearer token is present in theAuthorizationheader,validateAuthenticatedSessionperforms a token exchange instead of redirecting to OAuthensureInstalledshortcut — when the token exchange strategy is on,ensureInstalledOnShopskips the session check and goes straight to embedding/loading the apphooks.afterAuth— async callback invoked after both OAuth and token exchange flows, deduplicated viaIdempotentPromiseHandlerto prevent double-firing on concurrent requestsregisterWebhooks({session})— convenience method onShopifyAppwrappingapi.webhooks.registerexpiringOfflineAccessTokensflag — threads the flag intoauth.callbackandauth.tokenExchangecallsensureOfflineTokenIsNotExpiredhelper — proactively refreshes offline tokens nearing expiry in the standard OAuth pathshopifyApp,validateAuthenticatedSession,auth, and a new token-exchange guide addedType of change
Checklist
pnpm changesetto create a draft changelog entry (do NOT update theCHANGELOG.mdfiles manually)