Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG]“X-Frame-Options“ issue when using "Accept Hosted iframe -- PCI SAQ A -- most secure" payment form type #7

Closed
dangtrinhtran opened this issue Oct 17, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@dangtrinhtran
Copy link

Hi @rhoerr

Thank you for the release of version 5.1.2.

🐛 Bug report

Current Behavior

Magento 2.4.7-p2, PHP 8.3, paradoxlabs/authnetcim 5.1.2 and "Accept Hosted iframe -- PCI SAQ A -- most secure" payment form type.

Expected Behavior

The payment iframe should be loaded without errors.

Minimal reproduction of the problem with instructions

Step 1: Enable "Payment Form Type: Accept Hosted iframe -- PCI SAQ A -- most secure".
Step 2: 'x-frame-options' => 'SAMEORIGIN' in app/etc/env.php or Header set X-Frame-Options SAMEORIGIN in .htaccess file.

Screenshot 2024-10-17 at 10 00 00 AM

If we set "Header unset X-Frame-Options", the payment iframe is loaded but we do not think it is a good way to do this because it could expose the site to clickjacking attacks.

Do you have any ideas about this?

What is the motivation / use case for changing the behavior?

Environment


Authnetcim version: 5.1.2
Magento version: 2.4.7-p2
PHP version: 8.3


Others:

@dangtrinhtran dangtrinhtran added the bug Something isn't working label Oct 17, 2024
@rhoerr
Copy link
Member

rhoerr commented Oct 17, 2024

Hi @dangtrinhtran , thanks for bringing this up.

We do have a KB article about this: https://support.paradoxlabs.com/support/solutions/articles/4000202094-authorize-net-cim-payment-gateway-failed-to-connect-or-no-message-received-from-communicator-

But to more directly answer your concern:

Context

The way the Authorize.net hosted form works requires a 'communicator' page on your website to be embedded inside the hosted form, to pass messages to your checkout page. That's how we know what size to make the form, and when the customer hits 'place order'. This is in direct conflict with X-Frame-Options=SAMEORIGIN though, which prohibits your site from being embedded in any external frame (including by Authorize.net).

As you found, Magento tries to force this header in multiple ways:

  • It does this in PHP via \Magento\Framework\App\Response\HeaderProvider\XFrameOptions, which always sets it to SAMEORIGIN. As far as I know, the env.php value doesn't have any effect now at all. (This probably changed in a security patch at some point.)
  • For some Apache servers, via pub/.htaccess:289 (as you noted): Header set X-Frame-Options SAMEORIGIN

We unset the PHP header for the communicator page only, using a plugin. However, if your server processes the Apache Header set rule, that overrides any PHP value for it, and forces SAMEORIGIN again. There's no way for us to change the header in this case. It's also possible for this to happen from a WAF or CDN service, such as Cloudflare, Sucuri, Fastly, or others.

Solution

Since X-Frame-Options is set by Magento core in PHP, you can safely remove the .htaccess line. When you do so, you should see that the communicator is no longer blocked, but all other site pages still return X-Frame-Options=SAMEORIGIN.

You can apply that change automatically with a composer patch such as:

Index: vendor/magento/magento2-base/pub/.htaccess
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/pub/.htaccess b/pub/.htaccess
--- a/pub/.htaccess
+++ b/pub/.htaccess	(date 1726771725229)
@@ -286,5 +286,6 @@
     </FilesMatch>

     ## Prevent clickjacking
-    Header set X-Frame-Options SAMEORIGIN
+    ## Handle X-Frame-Options in PHP
+    # Header set X-Frame-Options SAMEORIGIN
 </IfModule>

Use vaimo/composer-patches if you don't already, save the above patch to your codebase, and apply it with composer.json configuration such as:

    "extra": {
        "patches": {
            "magento/magento2-base": {
                "Disable htaccess frame-options": "patches/disable-frame-options-sameorigin.patch"
            },
        },
    },

Other notes

I would argue Magento is in the wrong for having this Header set line in pub/.htaccess at all, because that is completely redundant to the PHP header code. But I doubt that will ever be removed from Magento core.

I deeply hope that Authorize.net improves how the Hosted form communicates status using modern web mechanisms, to avoid this problem like all other embedded payment gateways. But for now, it's what we have.

We do need to improve communication around this issue, as it does come up a lot.

There is a theoretical alternative approach, where we accept that the form won't always be able to communicate, and pass messages through your web server and Authorize.net webhooks (for success/failure) instead. But this would be very fraught, as there's potentially significant delay between when a customer clicks 'place order' and when the webhook comes through and then gets from the server to the customer browser to send them to the order success page. That's assuming the webhook goes through at all. If nothing else, it would be going from one round-trip to Authorize.net, to that round trip, plus an async notification, plus two more jumps (Authnet -> server, server -> client, by some means). In other words, slow, and lots of pieces involved.

Another approach would be to change to a payment redirect, where the customer places their order, gets redirected to Authorize.net for payment, and then redirected back to your confirmation/success page. That would avoid the issue, but we don't consider that acceptable user experience.

@dangtrinhtran
Copy link
Author

@rhoerr thanks for the details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants