firebase / firebase-functions

Firebase SDK for Cloud Functions
https://firebase.google.com/docs/functions/
MIT License
1.01k stars 202 forks source link

Don't verify auth token on public endpoints #1557

Open AlexJetplan opened 2 months ago

AlexJetplan commented 2 months ago

[REQUIRED] Version info

node:

v18.19.0

firebase-functions: 4.9.0

firebase-tools:

13.5.2

firebase-admin: 12.0.0

[REQUIRED] Test case

export const heartbeat = onCall(() => {
    const data  = {
        isConnected: true,
        timestamp: new Date().getTime(),
    }

         return data
})

[REQUIRED] Steps to reproduce

[REQUIRED] Expected behavior

Since it's a public endpoint it should always return a response, no matter if the token is provided, valid, or invalid. I have had cases in the past where the js SDK would cause the token to become invalid and users couldn't access public endpoints anymore, one of which was a heartbeat endpoint to make sure the user is still connected.

[REQUIRED] Actual behavior

The request is rejected when you provide an auth header with an invalid token.

Were you able to successfully deploy your functions?

Yes

google-oss-bot commented 2 months ago

I found a few problems with this issue:

colerogers commented 1 month ago

Hey @AlexJetplan you need to set the invoker to public to allow the function to serve public requests. You can put it directly in the options object where you specify cors (or alternatively in the global options for all funcitons):

export const heartbeat = onRequest({ cors: true, invoker: "public" }, (request, response) => {
    const data  = {
        isConnected: true,
        timestamp: new Date().getTime(),
    }
    response.json({ data })
})

Thanks

AlexJetplan commented 1 month ago

Hey @AlexJetplan you need to set the invoker to public to allow the function to serve public requests. You can put it directly in the options object where you specify cors (or alternatively in the global options for all funcitons):

export const heartbeat = onRequest({ cors: true, invoker: "public" }, (request, response) => {
  const data  = {
      isConnected: true,
      timestamp: new Date().getTime(),
  }
  response.json({ data })
})

Thanks

Hey, my apologies, I posted the wrong sample code, the issue was in regards to onCall. In fact if you use onRequest as described in my post it actually works, it only doesn't work when you use onCall.

The issue also isn't that it isn't publicly available, the issue is that it is accessible by anybody but at the same time if you provide an invalid token it will reject the request.

I have updated the issue with the code that won't work, my apologies!

exaby73 commented 1 month ago

Hey @AlexJetplan. How are you invoking this function? Via an HTTPS request?

AlexJetplan commented 1 month ago

Hey @AlexJetplan. How are you invoking this function? Via an HTTPS request?

Hey!

In our app we are invoking it using the firebase sdk, but for you to reproduce the issue more easily you can just use a regular https client like postman or curl or whatever you want, anything will work. The important bit is that you have to send a request that has the Authorization header with an invalid token.