[Feedback for php package]

I have reproduced the issue on the latest CLI version.

Yes, I am on the latest version

I have searched existing posts and this report is not a duplicate.

Yes, this isn’t a duplicate

In which of these areas are you experiencing a problem?

PHP Library

Expected behavior

Clicking in my app to navigate to that URL within the iframe.

Actual behavior

I have set it up using Laravel for an App Home app.The only problem I have is navigation within the iframe.When I use Polaris component I get the following error: Embedded app without id_token. Redirect to the patch ID token page to obtain a new token using the provided response.

But when I use the everything works like expected.My thought was that the App Bridge would intercept the link clicks and add the required GET params / headers.But it doesn’t seem to work.

I’d love to hear what you think it is!

Reproduction steps

Follow the shopify-app-php instructions for Laravel.
Then wrap your routes in this middleware:

<?php namespace App\Http\Middleware; use App\Http\Responses\ShopifyResponse; use App\Models\ShopifyAccessToken; use Closure; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\Request; use Shopify\App\ShopifyApp; use Symfony\Component\HttpFoundation\Response; class VerifyShopifyRequest { public function handle(Request $request, Closure $next): Response { $shopify = app(ShopifyApp::class); $req = [ "method" => $request->method(), "headers" => $request->headers->all(), "url" => $request->fullUrl(), "body" => $request->getContent(), ]; $result = $shopify->verifyAppHomeReq( $req, appHomePatchIdTokenPath: "/auth/patch-id-token", ); if (!$result->ok) { return ShopifyResponse::from($result->log, $result->response); } try { $accessToken = ShopifyAccessToken::query() ->where("shop", $result->shop) ->where("access_mode", "offline") ->firstOrFail(); $refreshResult = $shopify->refreshTokenExchangedAccessToken([ "shop" => $accessToken->shop, "accessMode" => $accessToken->access_mode, "token" => $accessToken->token, "scope" => $accessToken->scope, "refreshToken" => $accessToken->refresh_token, "expires" => $accessToken->expires, "refreshTokenExpires" => $accessToken->refresh_token_expires, ]); if (!$refreshResult->ok) { return ShopifyResponse::from( $refreshResult->log, $refreshResult->response, ); } if (isset($refreshResult->accessToken)) { $accessToken->update([ "token" => $refreshResult->accessToken->token, "scope" => $refreshResult->accessToken->scope, "refresh_token" => $refreshResult->accessToken->refreshToken, "expires" => $refreshResult->accessToken->expires, "refresh_token_expires" => $refreshResult->accessToken->refreshTokenExpires, ]); } } catch (ModelNotFoundException) { $exchangeResult = $shopify->exchangeUsingTokenExchange( accessMode: "offline", idToken: $result->idToken, invalidTokenResponse: $result->newIdTokenResponse, ); if (!$exchangeResult->ok) { return ShopifyResponse::from( $exchangeResult->log, $exchangeResult->response, ); } ShopifyAccessToken::create([ "shop" => $exchangeResult->accessToken->shop, "access_mode" => $exchangeResult->accessToken->accessMode, "token" => $exchangeResult->accessToken->token, "scope" => $exchangeResult->accessToken->scope, "refresh_token" => $exchangeResult->accessToken->refreshToken, "expires" => $exchangeResult->accessToken->expires, "refresh_token_expires" => $exchangeResult->accessToken->refreshTokenExpires, ]); } $request->merge([ "shop" => $result->shop, "shopifyHeaders" => $result->response->headers ?? [], ]); $response = $next($request); foreach ($request->input("shopifyHeaders", []) as $header => $value) { $response->headers->set($header, $value); } return $response; } } ### Verbose output Shopify\App\Types\ResultWithExchangeableIdToken {#288 ▼ // app/Http/Middleware/VerifyShopifyRequest.php:30 +ok: false +shop: null +idToken: null +userId: null +newIdTokenResponse: null +log: Shopify\App\Types \ LogWithReq { #290 ▼ +code: "redirect_to_patch_id_token_page" +detail: "Embedded app without id_token. Redirect to the patch ID token page to obtain a new token using the provided response." +req: array:4 [▼ "method" => "GET" "headers" => array:27 [▶] "url" => "http://signatures-proceedings-neither-inspiration.trycloudflare.com/sales" "body" => "" ] } +response: Shopify\App\Types \ ResponseInfo { #291 ▼ +status: 302 +body: "" +headers: array:1 [▼ "Location" => "http://signatures-proceedings-neither-inspiration.trycloudflare.com/auth/patch-id-token?shopify-reload=%2Fsales" ] } } ### Operating system NixOS ### CLI version 3.91.0 ### Shell bash ### Nodejs version v22.22.0 ### What language and version are you using in your application? PHP 8.2