ampproject / amp-toolbox

A collection of AMP tools making it easier to publish and host AMP pages.
Apache License 2.0
450 stars 242 forks source link

@ampproject/toolbox-cors error on submitting amp-form from amp-email #1108

Open davecook88 opened 3 years ago

davecook88 commented 3 years ago

Following all of the setup instructions in the readme, @ampproject/toolbox-cors allows my amp-lists to retrieve dynamic content but when submitting an amp-form, the following error is displayed:

Uncaught (in promise) Error: Class$obf_1009: [https://dynamicmail-pa.googleapis.com/v2/xhrs:proxy?alt=protojson] Cg: Unsupported HTTP status: 400: Class$obf_1011: [object Object]

log.js:258 [amp-form] Form submission failed: Error: Request viewerRenderTemplate failed: Error: Class$obf_1009: [https://dynamicmail-pa.googleapis.com/v2/xhrs:proxy?alt=protojson] Cg: Unsupported HTTP status: 400: Class$obf_1011: [object Object]

I can see from my logs that the request is never reaching my server.

Here is a minimal version of my server setup for reference https://github.com/davecook88/firebase-minimal

sebastianbenz commented 3 years ago

Hm. that's hard to tell from the error. In your sample code (which looks fine) I've noticed that you're manually configuring cors as well: https://github.com/davecook88/firebase-minimal/blob/master/functions/index.js#L39. Not sure though whether that's a problem in your case.

sebastianbenz commented 3 years ago

@patrickkettner are you aware of any specifics to how AMP email handles post requests that could be a problem here?

patrickkettner commented 3 years ago

It looks like gmail is blocking the request at the XHR proxy. CORS in amp4email require special configuration to be supported - Here are the docs

davecook88 commented 3 years ago

@patrickkettner

Thank you very much for your response. I understand that the email:true flag in the toolbox library should handle this, though?

I've followed the instructions in the link and I've met the same issue. Also, I'm confused as to why this would be ok in AMP playground but not in Gmail.

@sebastianbenz

To be honest, I've tried everything I can possibly think of, manually configuring CORS, using this library, and a combination of the two. I can say that when those lines are commented out, the issue is the same.

When sending the POST requests from AMP playground, I can follow the process pretty easily from the request in the browser to my server. It seems that when sending from the Gmail context, the request is routed through the AMP cache (which the verifyOrigin flag in the toolbox whitelists, as I understand).

When sending the POST request from Gmail, the request never hits my server and, as the error messages are quite opaque, I'm unsure as to what the precise issue is.

davecook88 commented 3 years ago

@patrickkettner following your response, I wanted to be totally sure that I had exhausted all of my options and I implemented the solution suggested in the documentation that you linked (commenting out the cors and ampCors library references).

This is what I came up with as a nodeJS version of the code on the page:

const isAllowedEmail = (email) => {
    return true; //["amp@gmail.dev"].includes(email);
};

app.use((req, res, next) => {
    let senderEmail;
    console.log("request received");
    console.log("headers", req.headers);
    if (req.headers["AMP-Email-Sender"]) {
        console.log("request received");
        senderEmail = req.headers["AMP-Email-Sender"];
        if (isAllowedEmail(senderEmail)) {
            res.set("AMP-Email-Allow-Sender", senderEmail);
        }
    } else if (req.headers["origin"]) {
        const reqOrigin = req.headers["origin"];
        if (!req.query.__amp_source_origin) {
            return next(new Error("Not allowed by CORS"));
        } else {
            senderEmail = req.query.__amp_source_origin;
            if (!isAllowedEmail(senderEmail)) {
                return next(new Error("Not allowed by CORS"));
            }
        }
        console.log("reqOrigin", reqOrigin);
        console.log("senderEmail", senderEmail);
        res.set("Access-Control-Allow-Origin", reqOrigin);
        res.set(
            "Access-Control-Expose-Headers",
            "AMP-Access-Control-Allow-Source-Origin"
        );
        res.set("AMP-Access-Control-Allow-Source-Origin", senderEmail);
        return next();
    }
});

If you can see anything that is incorrect here, please let me know.

Even with this, the result is the same. The amp-lists populate correctly. The amp-forms submit from the playground contexts but the same errors are being returned from the XHR proxy.

patrickkettner commented 3 years ago

Would you be able to share the contents of the you are loading that is attempting this fetch?

The error in your original report, that is the devtools console output on gmail.com? Do you see the XHR request firing that triggers that 400? Are you able to see if it is including the required AMP-Email-Sender and AMP-Email-Allow-Sender headers?

davecook88 commented 3 years ago

Thanks again for taking the time to answer. Yes, the errors in my original post are the devtools console errors that show up when I submit the form.

I can see the XHR request. As opposed to when I locate this in the playground, I can see a lot of other codes injected into the request, which I'm wary to make public just incase there's a security risk involved.

The response is:


--batch__V0SyTdSGFOz3Ntwv6DZ2oex4lM3vzwD
Content-Type: application/http
Content-ID: <response-batch627546551269428321+gapiRequest@googleapis.com>

HTTP/1.1 400 Bad Request
Vary: Origin
Vary: X-Origin
Vary: Referer
Content-Type: application/json+protobuf; charset=UTF-8

{"1":3,"2":"Request contains an invalid argument."}
--batch__V0SyTdSGFOz3Ntwv6DZ2oex4lM3vzwD--

I can see that the origin matches on the request and the response:

request:

origin: https://mail.google.com
referer: https://mail.google.com/

response:

access-control-allow-origin: https://mail.google.com

The only query string parameter I can see is this:

%24ct: multipart%2Fmixed%3B%20boundary%3Dbatch627546551269428321

I can't see AMP-Email-Sender and AMP-Email-Allow-Sender headers. I was assuming that these would be added by the proxy. I can see the sender email address in the payload, along with other codes etc added by Gmail.

As I mentioned, I can't see that the request ever reaches my server.

davecook88 commented 3 years ago

Is there any news on this? Is it safe to say that this is an issue with the library?

davecook88 commented 3 years ago

I've received an answer from someone at Google about this.

There's a bug with AMP forms submitting with enctype=3D"application/x-www-form-urlencoded" which has been submitted for resolution.

I'll update this thread when I have an update on the ticket.

zhangsu commented 2 years ago

FYI this bug should now be fixed in Gmail.