invertase / stripe-firebase-extensions

Repository of Firebase Extensions built by Stripe.
https://firebase.google.com/products/extensions
Apache License 2.0
436 stars 164 forks source link

[FAQ] CORS error when calling function #59

Closed Kevin-Andries closed 2 years ago

Kevin-Andries commented 4 years ago

I'm running through a very annoying issue when calling createPortalLink function.

I always get the following error : "Access to fetch at 'https://*name-of-my-project*.cloudfunctions.net/createPortalLink' from origin 'https://*my-app*.firebaseapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request"

This happens only when I try to call a function from this extension, not my own.

It is not only happening when I test on localhost, but also when it is deployed on firebase hosting.

Any idea on how I could solve it ?

Thanks for your help.

thorsten-stripe commented 4 years ago

@Hadrons27 from what I've seen this is most often related to a wrong location setting for the function call. E.g. if your function is running on us-east1 you need to explicitly set that:

const functionRef = firebase
  .app()
  .functions('us-east1') // <-- need to specify correct location.
  .httpsCallable('ext-firestore-stripe-subscriptions-createPortalLink');
const { data } = await functionRef({ returnUrl: window.location.origin });
window.location.assign(data.url);

You can find the location for your function in the region column here: https://console.firebase.google.com/u/0/project/_/functions/list

Kevin-Andries commented 4 years ago

Hi, thank you for your answer, but I am already calling the function with the right region, which is europe west 3.

thorsten-stripe commented 4 years ago

@Hadrons27 do you have a link to your code or can copy and paste it here?

Kevin-Andries commented 4 years ago

My code is really simple, I'm using flutter web. The code where I call my function is here :

final HttpsCallable callable = CloudFunctions(region: 'europe-west3').getHttpsCallable(functionName: 'createPortalLink'); var result = await callable.call(<String, dynamic> { 'returnUrl': "https://www.somewebsite.com" });

thorsten-stripe commented 4 years ago

Thanks. You will need to pass the full function name, including the extension name prefix. If you've installed the extension with default settings the function name will be ext-firestore-stripe-subscriptions-createPortalLink, otherwise you can check the function name in your project's function list when hovering over the function name: https://console.firebase.google.com/u/0/project/_/functions/list image

Kevin-Andries commented 4 years ago

Oh, thank you so much, I feel a bit stupid now. It is working great !

Have a nice day

thorsten-stripe commented 4 years ago

Don't, I ran into exactly this (and the location issue) myself in the beginning and had to ask the Firebase team!

I'm going to leave this issue open in case anyone else runs into this, and also to keep that that we should add this to an FAQ in the future.

benjaminrosenberg commented 3 years ago

Hi @thorsten-stripe

I'm getting this error when running the posted code snippet:

Error: internal
at new HttpsErrorImpl
at _errorForRespons
at Service.<anonymous>
at step
at Object.next
at fulfilled

snippet:

const functionRef = firebase
  .app()
  .functions('us-east1') // <-- need to specify correct location.
  .httpsCallable('ext-firestore-stripe-subscriptions-createPortalLink');
const { data } = await functionRef({ returnUrl: window.location.origin });
window.location.assign(data.url);

The error is thrown when running the line const { data } = await functionRef({ returnUrl: window.location.origin });

thorsten-stripe commented 3 years ago

@benjaminrosenberg can you post a screenshot of the error and the context? As in where do you see it? Is it in the chrome dev console? Which browser are you using etc.

Also, in your Firebase console, can you please check the logs of the ext-firestore-stripe-subscriptions-createPortalLink function and post any error messages you see there here as well. Thanks.

benjaminrosenberg commented 3 years ago

@thorsten-stripe , sure. There's not much more info in the screenshot. I am catching the error: image

Here's a screenshot of the code: image

I don't see anything that would suggest there is an error in firebase: image

Thanks!

benjaminrosenberg commented 3 years ago

@thorsten-stripe, looks like this was a firebase error! I was using version 7.22.0 and in the release notes of 7.22.1 they mentioned a fix for callable functions. Simply upgrading allowed this function to work perfectly. Thanks!

https://firebase.google.com/support/release-notes/js#cloud-functions-for-firebase-client-sdk

pfloresl commented 3 years ago

Him I am getting similar issues, this is code

const functionRef = firebase .app() .functions('us-central1') .httpsCallable( 'ext-firestore-stripe-subscriptions-createCustomer', ); functionRef(params) .then((data) => { console.log(data); }) .catch((error1) => { console.log(error1); });

error1 is

Error: internal at new HttpsErrorImpl (error.ts:65) at _errorForResponse (error.ts:175) at Service.<anonymous> (service.ts:263) at step (tslib.es6.js:100) at Object.next (tslib.es6.js:81) at fulfilled (tslib.es6.js:71)

i also see in chrome debugger,

Access to fetch at 'https://us-central1-navigation-development.cloudfunctions.net/ext-firestore-stripe-subscriptions-createCustomer' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

using chrome;firebase 8.2.3 but on 7.17.2 too

pfloresl commented 3 years ago

I am also presuming that this is valid usage and that i can create a new stripe user by making this function call, and i don't need to wait until a checkout.
On Safari and in production i am getting in the debugger, Preflight response is not successful, On Firefox, image

thorsten-stripe commented 3 years ago

@pfloresl the createCustomer is an internal function that is triggered by a new user signing up via Firebase auth (see https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-subscriptions/functions/src/index.ts#L81). It is not a callable function, that's why you're seeing the error. The extension automatically creates the Stripe customer objects for you, so you won't need to call the function yourself.

pfloresl commented 3 years ago

Yes, thank you.

JoBeDev commented 3 years ago

Hi @thorsten-stripe I seem to be getting the same issue.

I have installed the Stripe extension and configured it to use australia-southeast1

I'm attempting to redirect a customer to the Stripe customer portal. I run the following code when a button is clicked in my web app:

`const functionRef = firebase.app().functions('australia-southeast1').httpsCallable('ext-firestore-stripe-subscriptions-createPortalLink');

const { data } = await functionRef({ returnUrl: window.location.origin }); window.location.assign(data.url);`

I then get the following error in the browser debugger:

:5000/#:1 Access to fetch at 'https://us-central1-**app-name**.cloudfunctions.net/ext-firestore-stripe-subscriptions-createPortalLink' from origin 'http://localhost:5000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

This is the case regardless of weather I attempt the request from my local environment or the app itself. Based on the error it looks like the fetch request is coming from us-central1 but I have definitely specified the correct location in my functions environment as well as my code.

Any help would be amazing.

Thanks Thor,

thorsten-stripe commented 3 years ago

@jhuleatt any idea on the one above and why it's not picking up australia-southeast1?

JoBeDev commented 3 years ago

@jhuleatt any idea on the one above and why it's not picking up australia-southeast1?

Hey guys, just wondering if there's any update on this. I've got another client project where I'm trying to use the portal and I'm getting the same issue.

Cheers,

Roc8Trppn commented 2 years ago

Hi, so I had the same problem (CORS Policy blocked...) when I realized that for me I didn't have anything to do with the region but the cloud function name was changed to "ext-firestore-stripe-payments-createPortalLink" instead of "ext-firestore-stripe-subscriptions-createPortalLink"...that solved it for me.. If you're not sure, just check the name of the cloud function in your firebase console under "Cloud Function", that was installed by the stripe-extension:

Bildschirmfoto 2021-12-28 um 15 57 17

Hope it might help someone

dackers86 commented 2 years ago

Closing this issue as a solution appears to have been provided.

In summary...

  1. Ensure you call you functions within the same region as the installed extension. For example with .functions('us-east1') // <-- need to specify correct location.

  2. Ensure you are using the extensions full function name, typically prefixed with ext-firestore-stripe.

eddimull commented 2 years ago

Hi, so I had the same problem (CORS Policy blocked...) when I realized that for me I didn't have anything to do with the region but the cloud function name was changed to "ext-firestore-stripe-payments-createPortalLink" instead of "ext-firestore-stripe-subscriptions-createPortalLink"...that solved it for me.. If you're not sure, just check the name of the cloud function in your firebase console under "Cloud Function", that was installed by the stripe-extension:

Bildschirmfoto 2021-12-28 um 15 57 17

Hope it might help someone

Thank you for not being a Denvercoder9, TrppnBstrds. That's exactly what was going on with me.

markslawton commented 2 years ago

I spent several days on this. The example code in stripe-subs-ext.web.app is incorrect. The line: .httpsCallable('ext-firestore-stripe-payments-createPortalLink'); IS WRONG the correct line is .httpsCallable('ext-firestore-stripe-payments-createPortalLink'); IS RIGHT

markslawton commented 2 years ago

Seems to me that the github example should be updated to save others from wasting days on this. (Especially because the error message makes one think it is a CORS problem when in fact it is a problem with the function name not existing as called.)

jsteele-stripe commented 2 years ago

@markslawton Can you please share where the old function name is still referenced?

marcopolodesign commented 2 years ago

Hello guys, I'm having the same issue here but when building the Customer Session Portal `app.post('/create-customer-portal-session', async (req, res) => { // Authenticate your user. res.set('Access-Control-Allow-Origin', '*'); res.setHeader( 'Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE' );

// Request headers you wish to allow res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

const session = await stripe.billingPortal.sessions.create({ customer: req.body.customer, // return_url : "https://lovesweatfitness.com/lsf-app/lsf" });

res.redirect(session.url); });`

the weird thing is that I'm running another functions on the same index.ts file and they seem to work. But when creating this new one I always get the same CORS issue. Did anybody find a plausible solution?

marcopolodesign commented 2 years ago

Hello guys, I'm having the same issue here but when building the Customer Session Portal `app.post('/create-customer-portal-session', async (req, res) => { // Authenticate your user. res.set('Access-Control-Allow-Origin', '*'); res.setHeader( 'Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE' );

// Request headers you wish to allow res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

const session = await stripe.billingPortal.sessions.create({ customer: req.body.customer, // return_url : "https://lovesweatfitness.com/lsf-app/lsf" });

res.redirect(session.url); });`

the weird thing is that I'm running another functions on the same index.ts file and they seem to work. But when creating this new one I always get the same CORS issue. Did anybody find a plausible solution?

jsteele-stripe commented 2 years ago

@marcopolodesign Your issue stems from doing res.redirect() server-side with (I assume) a fetch network request to your create-customer-portal-session endpoint. You should return your session JSON to your front-end and redirect there.

abulka commented 2 years ago

@markslawton The two function calls you refer to viz. .httpsCallable('ext-firestore-stripe-payments-createPortalLink'); as being different are identical in your comment. I think you might have pasted the same function call twice, rather than one of them being the wrong one? Presumably the wrong one is 'ext-firestore-stripe-subscriptions-createPortalLink' (with the word subscriptions in it).

Masterxilo commented 1 year ago

@Roc8Trppn same problem here, nice find!

The cloud function that the Stripe Firebase Extension creates is now called:

ext-firestore-stripe-payments-createPortalLink

but the code I use, following the tutorial: https://firebase.google.com/codelabs/stripe-firebase-extensions refers to the function name:

ext-firestore-stripe-subscriptions-createPortalLink

which does not exist. Beats me why this is reported as a CORS error...

you can also see the difference if you go to the url: the wrong url

https://europe-west3-stripesubscription-638ee.cloudfunctions.net/ext-firestore-stripe-subscriptions-createPortalLink

gives a 403. The right one

https://europe-west3-stripesubscription-638ee.cloudfunctions.net/ext-firestore-stripe-payments-createPortalLink

gives a 400, bad request when called like this.

@thorsten-stripe please update the tutorial: https://firebase.google.com/codelabs/stripe-firebase-extensions#4 it should read


    // Call billing portal function
    const functionRef = firebase
      .app()
      .functions(functionLocation)
      .httpsCallable("ext-firestore-stripe-payments-createPortalLink");
plaimanus commented 1 year ago

I have to active customer portal link in stripe dashboard to make it work https://dashboard.stripe.com/test/settings/billing/portal

mutaremalcolm commented 10 months ago

Hi everyone i seem to be facing the same issue: Im making a call to Stripe from the frontend and also have firebase installed for the store:

The code for the fetch request is below: const response = await fetch('/.netlify/functions/create-payment-intent', { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 10000}) }).then((res) => { console.log("Response form fetch /netlify-functions - was true ✅ --> respone: ", res.json()) return res.json(); });

  response.headers.append('Access-Control-Allow-Origin', '*'); // Allow all origins 
  console.log(response);

}