Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

DanielJohan's avatar

CORS Preflight Request Triggered on Stripe Redirect

I am encountering a CORS error when attempting to redirect a user to Stripe Checkout after applying the auth and verified middleware in my Laravel application.

If the user is already logged in, this issue does no occur and the user is successfully redirected to the stripe checkout.

Expected Behavior

  • A logged-in and verified user accesses the /checkout route.
  • The CheckoutController handles the request, creates a Stripe checkout session, and redirects the browser to the Stripe payment page (303 See Other response).

Observed Behavior When a user who is not logged in or verified initially accesses the /checkout route:

  1. The auth and verified middleware redirect the user to /login with a 302 Found response.
  2. After logging in, the browser is redirected back to /checkout.
  3. The CheckoutController triggers a 303 See Other response to Stripe's checkout URL.

However, at this point, the browser sends a preflight OPTIONS request to Stripe's checkout URL, which fails with a 403 Forbidden error:

Access to XMLHttpRequest at 'https://checkout.stripe.com/c/pay/...' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present.

What I Have Tried

  • When middleware is bypassed (i.e., the user is already logged in and verified), the redirect to Stripe works fine without triggering any CORS issues.
  • The middleware sequence seems to introduce intermediate redirects, which may cause the browser to handle the final redirect differently.

Code Snippet Here is the relevant portion of my CheckoutController:

public function __invoke(Request $request, string $plan = 'price_CTwJCLOwyI')
{
    $user = $request->user();
    $subscription = $user->subscriptions()
        ->where('stripe_status', 'active')
        ->where('type', 'prod_UOt6xDoI')
        ->first();

    if ($subscription) {
        return redirect()->route('book-selection')->with('message', 'You are already subscribed.');
    }

    return $request->user()
        ->newSubscription('prod_iUOt6xDoI', $plan)
        ->checkout([
            'success_url' => route('book-selection'),
            'cancel_url' => route('book-selection'),
        ]);
}

Route definition:

Route::get('/checkout', CheckoutController::class)
    ->middleware(['auth', 'verified'])
    ->name('checkout');

Questions

  1. Why does the browser treat the server-side redirect to Stripe as a CORS-triggering request when middleware redirects are involved?
  2. Is there a way to ensure that the final redirect behaves the same regardless of middleware involvement?
  3. Would handling the redirect to Stripe on the frontend (e.g., via JavaScript) be a better approach?

Any insights or recommendations would be greatly appreciated!

0 likes
2 replies
aprilnieves's avatar

Hello @ geometry dash lite, I think can answer your questions.

  1. When a user who is not authenticated accesses the /checkout route, the middleware redirects them to the /login route. Upon successful login, the user is redirected back to the /checkout route. This chain of redirects can affect how the browser handles the final redirect to the Stripe URL.

The browser is likely interpreting the final redirect to Stripe as a cross-origin request due to the sequence of redirects. Specifically, the initial redirect from the /checkout route to the /login route and back can cause the browser to treat the checkout as an AJAX request, which triggers a preflight OPTIONS request. If the Access-Control-Allow-Origin header is not present in the response from Stripe, the browser will block this request due to CORS policy.

  1. One approach to mitigate this issue is to ensure that the redirect to Stripe does not involve any intermediate steps that could trigger CORS. Here are a few strategies:

Direct Checkout Initialization: Instead of handling the checkout logic after the user logs in, consider initializing the Stripe checkout process directly in the login flow. After the user logs in, you can redirect them to the checkout session without involving intermediate middleware. Session Storage: Store the intended destination (like the plan) in the session before redirecting to the login page. After login, you can retrieve this value and directly create the Stripe checkout session. Use JavaScript for Redirection: Instead of a server-side redirect, you could handle the final redirect to Stripe via JavaScript on the client side. This way, you would avoid the CORS preflight issue entirely.

  1. Yes, handling the redirect to Stripe on the frontend can be a more effective solution. Here’s how you can implement this:

Create the Checkout Session: When the user accesses the checkout route and is authenticated, generate the checkout session on the server, but return the session URL to the client instead of redirecting immediately. Client-Side Redirect: Use JavaScript to redirect the user to the Stripe checkout URL. This can be accomplished with a simple JavaScript redirect after receiving the URL from the server. Here’s a brief outline of how the code might look:

php

Copy // CheckoutController public function __invoke(Request $request, string $plan = 'price_CTwJCLOwyI') { // ... your subscription logic ...

// Create a checkout session here and return the session URL
$session = $request->user()
    ->newSubscription('prod_iUOt6xDoI', $plan)
    ->checkout([
        'success_url' => route('book-selection'),
        'cancel_url' => route('book-selection'),
    ]);

// Return the session URL as a JSON response
return response()->json(['url' => $session->url]);

} And then on the frontend:

javascript

Copy // Assuming you're using Axios or Fetch axios.get('/checkout') .then(response => { window.location.href = response.data.url; // Redirect to Stripe });

martinbean's avatar

@danieljohan You‘re getting a CORS error because you seem to be trying to access the route via AJAX. The error message even says so, as it mentions “XMLHttpRequest”.

Why are you trying to do this in JavaScript? Just do a regular browser page visit so that if a redirect response is returned, then the user is redirected.

Please or to participate in this conversation.