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

request.auth is null in Firestore Rules when called from Firebase JS SDK in UWP #1491

Closed
tomasszabo opened this issue Jan 22, 2019 · 53 comments

Comments

@tomasszabo
Copy link

I've discovered a problem when querying Firestore from UWP Universal Javascript project with Firebase JS SDK.

Problem description

Problem occurs when querying Firestore with authenticated user and Firestore Security Rules set to:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: 
      	if request.auth.uid != null;        
    }
  }
}

I'm always receiving:

FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

With try and fail method I was able to find out that 'request.auth' object is 'null' in Security Rules because with following rule I'm able to successfully query Firestore:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: 
      	if request.auth == null;   
    }
  }
}

However this Security Rule enables reading of data for everyone and stored data will not be secured.

In my opinion, the problem is related to the fact that access token is not processed (therefore request.auth is null). The only difference I've found is that HTTP header is NOT 'Origin: file://' (Origin header is completely missing) and CORS headers are not set correctly set in Response (CORS header are missing, but I'm not sure if this is the reason why access token is not processed).

Expected behavior

Auth token should be processed and Firestore Security Rules applied accordingly.

Attachements

UWP Project to reproduce the error (need some Firebase Test project and Firebase user):

https://1drv.ms/u/s!AjL4mBIpdvWDnYZqNkla5hHjjguGVg

HTTP Request from UWP:


   Request URL: https://firestore.googleapis.com/google.firestore.v1beta1.Firestore/Listen/channel?database=projects%2__project__%2Fdatabases%2F(default)&VER=8&RID=21133&CVER=22&X-HTTP-Session-Id=gsessionid&%24httpHeaders=Authorization%3ABearer%20__access-token__%0D%0AX-Goog-Api-Client%3Agl-js%2F%20fire%2F5.7.2%0D%0A&zx=7qsckzfmr536&t=1
   Request Method: POST
   Status Code: 200 / 
 
 - Request Headers
   Accept: */*
   Accept-Encoding: gzip, deflate, br
   Accept-Language: en-US, en; q=0.7, cs; q=0.3
   Cache-Control: no-cache
   Content-Length: 662
   Content-Type: application/x-www-form-urlencoded
   Host: firestore.googleapis.com
   User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; MSAppHost/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134
 
 - Response Headers
   alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"
   cache-control: private
   content-encoding: gzip
   content-length: 71
   content-type: text/plain; charset=utf-8
   date: Tue, 01 Jan 2019 19:15:19 GMT
   server: ESF
   x-client-wire-protocol: h2
   x-content-type-options: nosniff
   x-frame-options: SAMEORIGIN
   x-http-session-id: GDPR57fJd-FfP6jaM98wCUpOO9SWVFty
   x-xss-protection: 1; mode=block

Javascript Console output:

Initializing firebase
main.js (49,5)
Signing in
main.js (55,5)
Signed in. Uid is G3nVlgyQIcWai7TN6nbBnmiJfBF2
main.js (69,9)
[2019-01-01T18:51:44.184Z]  @firebase/firestore: Firestore (5.7.2) [FirestoreClient]: Initializing. user= G3nVlgyQIcWai7TN6nbBnmiJfBF2
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.186Z]  @firebase/firestore: Firestore (5.7.2) [MemoryPersistence]: Starting transaction: Get last stream token
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.186Z]  @firebase/firestore: Firestore (5.7.2) [MemoryPersistence]: Starting transaction: Get next mutation batch
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.188Z]  @firebase/firestore: Firestore (5.7.2) [MemoryPersistence]: Starting transaction: Allocate query
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.188Z]  @firebase/firestore: Firestore (5.7.2) [MemoryPersistence]: Starting transaction: Execute query
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.189Z]  @firebase/firestore: Firestore (5.7.2) [MemoryPersistence]: Starting transaction: Remote document keys
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.189Z]  @firebase/firestore: Firestore (5.7.2) [Connection]: Creating WebChannel: https://firestore.googleapis.com/google.firestore.v1beta1.Firestore/Listen/channel [object Object]
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.195Z]  @firebase/firestore: Firestore (5.7.2) [Connection]: Opening WebChannel transport.
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.196Z]  @firebase/firestore: Firestore (5.7.2) [Connection]: WebChannel sending: {"database":"projects/xxx/databases/(default)","addTarget":{"query":{"structuredQuery":{"from":[{"collectionId":"settings"}],"where":{"fieldFilter":{"field":{"fieldPath":"createdBy"},"op":"EQUAL","value":{"stringValue":"G3nVlgyQIcWai7TN6nbBnmiJfBF2"}}},"orderBy":[{"field":{"fieldPath":"__name__"},"direction":"ASCENDING"}]},"parent":"projects/xxx/databases/(default)"},"targetId":2}}
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.390Z]  @firebase/firestore: Firestore (5.7.2) [Connection]: WebChannel transport opened.
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.496Z]  @firebase/firestore: Firestore (5.7.2) [Connection]: WebChannel received: {"targetChange":{"targetChangeType":"ADD","targetIds":[2]}}
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.652Z]  @firebase/firestore: Firestore (5.7.2) [Connection]: WebChannel received: {"targetChange":{"targetChangeType":"REMOVE","targetIds":[2],"cause":{"code":7,"message":"Missing or insufficient permissions."}}}
firebase-firestore.js (1,605)
[2019-01-01T18:51:44.653Z]  @firebase/firestore: Firestore (5.7.2) [MemoryPersistence]: Starting transaction: Release query
firebase-firestore.js (1,605)
error on snapshot FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
main.js (81,17)
   "error on snapshot"
   {
      [functions]: ,
      __proto__: { },
      code: "permission-denied",
      description: "Missing or insufficient permissions.",
      message: "Missing or insufficient permissions.",
      name: "FirebaseError",
      stack: "FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
   at e (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:71386)
   at t.prototype.fromRpcStatus (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:138184)
   at t.prototype.fromWatchChange (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:147575)
   at e.prototype.onMessage (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:262030)
   at Anonymous function (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:260812)
   at Anonymous function (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:261598)
   at Anonymous function (https://www.gstatic.com/firebasejs/5.7.2/firebase-firestore.js:1:169060)"
   }
@google-oss-bot
Copy link
Contributor

I found a few problems with this issue:

  • I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
  • This issue does not seem to follow the issue template. Make sure you provide all the required information.
@625dennis
Copy link

I'm having the same issue

@mikelehen
Copy link
Contributor

@bojeil-google Do you know if there are any known issues with getting auth tokens in UWP (Universal Windows Platform) applications? I'm not sure if this is a problem on the auth side or the Firestore side. It looks like there's no Authorization header in the request, which suggests we got no token (or else it somehow got stripped from the XHR!?).

@bojeil-google
Copy link
Contributor

I don't know much about UWPs and their intricacies. I remember there were some CORS issues in the past for file:// origins, but I thought they were resolved. I am not sure if this has to do with that.
It appears that the user is able to sign in (which means that the auth APIs and the calls to Auth server are working) from the console log, but somehow Firestore server is not able to get it.

@mikelehen
Copy link
Contributor

@bojeil-google Thanks! Yeah, I don't know much either, unfortunately. Strangely this sounds similar to a report we got about an Electron app recently, but probably coincidence.

@625dennis @tomasszabo As a sanity check, could one of you add something like firebase.auth().currentUser.getIdToken().then(token => console.log('got token', token)) and verify you get a non-null token back?

@625dennis
Copy link

I'm developing with nuxt and I think the problem is with the nuxt server not having a local store. I will try to resolve it with cookie storage.

@tomasszabo
Copy link
Author

@mikelehen Yes, the command you specified returns a non-null token. I've put it just before querying Firestore.

@bojeil-google UWP is not sending origin header at all (see "HTTP request from UWP" in my original post above). UWP is using ms-appx-web protocol, not file protocol, maybe that's the reason they're not filling origin header in requests.

@developius
Copy link

developius commented May 14, 2019

I've got a feeling that this is a deeper issue with Firestore Security Rules.

When testing my rules in the simulator, everything is working fine until I run an unauthenticated test - I get a null reference error:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      // allow anyone to read anything (we don't require auth in the app)
      allow read: if true
      // allow admins to do anything
      allow write: if isAdmin(request.auth.uid)
    }
    
    function isAdmin(uid) {
    	return isAuthenticated() &&
               userExists(uid) &&
               "admin" in getUser(request.auth.uid) &&
               getUser(uid).admin == true
    }
    
    function getUser(uid) {
    	return get(/databases/$(database)/documents/users/$(request.auth.uid)).data
    }
    
    function userExists(uid) {
    	return exists(/databases/$(database)/documents/users/$(request.auth.uid))
    }
    
    function isAuthenticated() {
    	return request.auth.uid != null; // null reference error
    }
  }
}

@tomasszabo, have you tried testing your rules in the simulator? What error do you get? You may need to check the raw response in dev tools to find it. For me, it doesn't seem to be able to resolve the request.auth object.

Update - solved
Just after posting this, I realised I might need to check if request.auth exists. This fixed it.

function isAuthenticated() {
    return request.auth != null && request.auth.uid != null;
}
@chrisgblr
Copy link

I'm having the same problem with some Internet Explorer 11 users.
If I set security rules to read and write for authenticated user only in Firestore I'm getting:
FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

Rules:
allow read, write: if request.auth != null && request.auth.uid != null;

If I remove these rules those Internet Explorer 11 user can access the data from Firestore.
So it seems like on some Internet Explorer 11 instances Firestore request aren't sent authenticated. On other Browsers the security rules work fine.

@thesandlord
Copy link

I'm still seeing the same issue that @aaachris is with IE11, and I can't figure out if there are any IE11 security settings that are causing issues.

@eirmag
Copy link

eirmag commented Aug 27, 2019

I do confirm having the exact same situation, and only in IE11. Firefox, chrome, edge are not affected by this situation. And the firebase.auth().currentUser.getIdToken().then(token => console.log('got token', token)) does send back a non-null token.

Nevertheless, as soon as we try to use onSnapshot, we get the

Uncaught Error in onSnapshot
code"permission-denied"
description"Missing or insufficient permissions."
message"Missing or insufficient permissions."
name"FirebaseError"

image

All of this with firebasejs 6.3.0

@ciriousjoker
Copy link

ciriousjoker commented Sep 10, 2019

Same problem here while using cordova. It works fine in the web version, but in the packaged app, request.auth seems to be null. The test from above is positive (ie I get a token back).

EDIT:
This problem seems to only exist in Chrome Dev 78. After changing the system Webview to the default one (stable 76), the problem was gone.

@mikelehen
Copy link
Contributor

@ciriousjoker What version of Firebase are you using? There was an auth-related race condition that was fixed in the latest release (6.6.0). Just want to make sure that's not what you're running into. Thanks!

@ciriousjoker
Copy link

ciriousjoker commented Sep 10, 2019

I'm using 6.6.0, but this problem was present in 6.0.2 as well.

@thesandlord
Copy link

@mikelehen 6.6.0 doesn't fix the problem in IE 11

@maxannear
Copy link

maxannear commented Oct 15, 2019

We're having this issue in Electron 7 (Chromium 68). Electron 6 (Chromium 76) works correctly. We're using firebase 7.2.0 in both cases.

We're using a custom auth tokens

firebase.auth().currentUser.getIdToken().then(token => console.log('got token', token))
returns the correct token.

Yet any time we try access Firestore we get FirebaseError: Missing or insufficient permissions.

@klaussner
Copy link

I ran into the same issue when I tried to use Firestore in a Firefox browser extension. Firestore requests fail with FirebaseError: "Missing or insufficient permissions." if the extension has the "<all_urls>" permission specified in its manifest, even though a user is signed in and is allowed to access all documents.

Here is a link to a minimal example repo: https://github.com/klaussner/firestore-firefox-extension-issue. The README.md lists the exact reproduction steps.

As has been discussed above, the problem seems to be how Firebase handles the HTTP Origin header. If a Firefox extension doesn't have the "<all_urls>" permission, the browser adds an Origin header (e.g., Origin: moz-extension://15a05323-f99f-3644-9304-508a5776b74d) to the XHRs sent to Firestore. However, if the extension has the "<all_urls>" permission, Firefox doesn't add this header (which, I think, is correct because the same-origin policy no longer applies).

It looks like the Firestore backend sets the auth object to null when it evaluates the Firestore rules if the request doesn't have an Origin header. Other Firebase services, including authentication and storage, work as expected.

@mikelehen
Copy link
Contributor

@klaussner Thanks for the info. Would it be possible for you to share examples of the network requests being sent (both the broken one without Origin and a working one with Origin)? Please remove the actual contents of the auth token and anything else sensitive, or email me directly at michael@firebase.com.

@ketan1062
Copy link

Hello @developius, Thanks for solutions. The solution saves my day.

@klaussner
Copy link

@mikelehen Here are the first two requests sent to Firestore, once with and once without Origin headers. I hope this helps. 🤞 Please let me know if you need more information.

First Request

URL: https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?database=[DATABASE]&VER=8&RID=95405&CVER=22&X-HTTP-Session-Id=gsessionid&%24httpHeaders=[TOKEN]&zx=o41gvibi0nw4&t=1

Request Headers

Host: firestore.googleapis.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: */*
Accept-Language: en,de;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 479
Origin: moz-extension://7eef82bd-5974-b84e-b4b5-15ea916f0bcc
Connection: keep-alive
TE: Trailers

Response Headers

HTTP/2.0 200 OK
x-client-wire-protocol: h2
x-http-session-id: -c1eQIx99Kaa-VdK3lFSkUlqLML2_CvK
content-type: text/plain; charset=utf-8
content-encoding: gzip
date: Tue, 03 Dec 2019 19:25:14 GMT
server: ESF
cache-control: private
content-length: 71
x-xss-protection: 0
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
access-control-allow-origin: moz-extension://7eef82bd-5974-b84e-b4b5-15ea916f0bcc
access-control-allow-credentials: true
access-control-expose-headers: x-client-wire-protocol,x-http-session-id
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
X-Firefox-Spdy: h2

Response Body

51
[[0,["c","2A3yo6U6BtLH5jlrG9Qfmg","",8,12,30000]]]

Second Request

URL: https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?database=[DATABASE]&gsessionid=Zm4JCnVrJZ-x4Du7mQoVd-tkvZCNMyio&VER=8&RID=rpc&SID=2A3yo6U6BtLH5jlrG9Qfmg&CI=0&AID=0&TYPE=xmlhttp&zx=x7eby92w90u6&t=1

Request Headers

Host: firestore.googleapis.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: */*
Accept-Language: en,de;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: moz-extension://7eef82bd-5974-b84e-b4b5-15ea916f0bcc
Connection: keep-alive
TE: Trailers

Response Headers

HTTP/2.0 200 OK
cache-control: private, max-age=0
x-content-type-options: nosniff
content-type: text/plain; charset=utf-8
content-encoding: gzip
date: Tue, 03 Dec 2019 19:25:14 GMT
server: ESF
x-xss-protection: 0
x-frame-options: SAMEORIGIN
access-control-allow-origin: moz-extension://7eef82bd-5974-b84e-b4b5-15ea916f0bcc
access-control-allow-credentials: true
access-control-expose-headers: x-client-wire-protocol,x-http-session-id
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
X-Firefox-Spdy: h2

Response Body

409
[[1,[{
  "targetChange": {
    "targetChangeType": "ADD",
    "targetIds": [
      2
    ]
  }
}
]],[2,[{
  "targetChange": {
    "targetChangeType": "CURRENT",
    "targetIds": [
      2
    ],
    "resumeToken": "CgkI9fXb+Zua5gI=",
    "readTime": "2019-12-03T19:31:47.191541Z"
  }
}
]],[3,[{
  "targetChange": {
    "resumeToken": "CgkI9fXb+Zua5gI=",
    "readTime": "2019-12-03T19:31:47.191541Z"
  }
}
]]]14
[[4,["noop"]]]14
[[5,["noop"]]]

❌⚡️

First Request

URL: https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?database=[DATABASE]&VER=8&RID=68201&CVER=22&X-HTTP-Session-Id=gsessionid&%24httpHeaders=[TOKEN]&zx=mf0pmb6655q&t=1

Request Headers

Host: firestore.googleapis.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: */*
Accept-Language: en,de;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 479
Connection: keep-alive
TE: Trailers

Response Headers

HTTP/2.0 200 OK
x-client-wire-protocol: h2
x-http-session-id: _wRLMJcSuFdFDVoCx4jW6RaI4eWLcDmQ
content-type: text/plain; charset=utf-8
content-encoding: gzip
date: Tue, 03 Dec 2019 19:29:16 GMT
server: ESF
cache-control: private
content-length: 71
x-xss-protection: 0
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
X-Firefox-Spdy: h2

Response Body

51
[[0,["c","rILgOaemnhCrHGXkUgfTdg","",8,12,30000]]]

Second Request

URL: https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?database=[DATABASE]&gsessionid=aX5IaaGrINK_oKA9GzeCENYYTUpPm4gI&VER=8&RID=rpc&SID=rILgOaemnhCrHGXkUgfTdg&CI=0&AID=0&TYPE=xmlhttp&zx=hfsvpk5t4xzf&t=1

Request Headers

Host: firestore.googleapis.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: */*
Accept-Language: en,de;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
TE: Trailers

Response Headers

HTTP/2.0 200 OK
cache-control: private, max-age=0
x-content-type-options: nosniff
content-type: text/plain; charset=utf-8
content-encoding: gzip
date: Tue, 03 Dec 2019 19:29:16 GMT
server: ESF
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
X-Firefox-Spdy: h2

Response Body

297
[[1,[{
  "targetChange": {
    "targetChangeType": "ADD",
    "targetIds": [
      2
    ]
  }
}
]],[2,[{
  "targetChange": {
    "targetChangeType": "REMOVE",
    "targetIds": [
      2
    ],
    "cause": {
      "code": 7,
      "message": "Missing or insufficient permissions."
    }
  }
}
]]]14
[[3,["noop"]]]14
[[4,["noop"]]]
@mikelehen
Copy link
Contributor

@klaussner Thank you! I will try to pull in some backend folks who may have insight into what's going on.

@mikelehen
Copy link
Contributor

@klaussner By the way, if you're willing to collect another data point, it would be interesting to know if transactions suffer from the same problem. Something along the lines of:

let db = firebase.firestore();
await db.runTransaction(transaction => {
  transaction.set(db.doc('example/foo'), {a: 1});
});

Transactions make direct REST requests instead of going through our WebChannel transport, so they may behave differently.

@klaussner
Copy link

@mikelehen Transactions are working without an Origin header. 👍

@mikelehen
Copy link
Contributor

I'm probably going to go ahead and put together a PR that checks for IE11 soon (today?). I can check for Electron too, assuming navigator.useragent.indexOf(' electron/') > -1) is sufficient. If anybody knows how to detect any of the other affected environments (Firefox extension, UWP apps) and wants to chime in, I may be able to include them in the PR as well.

@tomasszabo
Copy link
Author

It looks like that User Agent for UWP on Windows 10 and Windows 10 Mobile (yeah, it still exists) contains MSAppHost/3.0 (not sure about that /3.0 if it's not incremented with new Windows versions), for Xbox it contains Xbox (yep, UWP Apps runs also on Xbox but have not tried that).

mikelehen pushed a commit that referenced this issue Dec 20, 2019
…ader.

There is a backend bug (b/145624756) causing $httpHeaders to be ignored if an Origin header is not sent.  Via #1491 we've found that several environments can run into this issue so until the backend issue is fixed we are excluding them from using $httpHeaders. This may incur an extra CORS preflight round-trip in some cases, but this is much better than having our Authorization header get ignored.
@mikelehen
Copy link
Contributor

Thanks @tomasszabo and @agray5! I have a proposed PR that should work around the issue for IE, Electron, and UWP: https://github.com/firebase/firebase-js-sdk/pull/2464/files

Unfortunately we likely won't have any JS SDK releases for the next couple weeks due to US holidays. If anybody needs the fix sooner, I can likely help create a manual build of the SDK or something.

@jburja
Copy link

jburja commented Dec 20, 2019

@mikelehen I believe my team might need to get a fix sooner if you could create a manual build if possible. We are also using AngularFire within our application as a wrapper around the SDK but I'm not sure if that would require a new build as well?

mikelehen pushed a commit that referenced this issue Dec 20, 2019
…ader. (#2464)

There is a backend bug (b/145624756) causing $httpHeaders to be ignored if the HTTP request doesn't have an Origin header.  Via #1491 we've found that several environments are running into this issue so until the backend issue is fixed we are excluding them from using $httpHeaders. This may incur an extra CORS preflight round-trip in some cases, but this is much better than having our Authorization header get ignored.
@mikelehen
Copy link
Contributor

@jburja It turns out you can npm install firebase@canary to get the fix immediately. Let me know if you need any additional info.

@ShishKabab
Copy link

ShishKabab commented Jan 6, 2020

#2464 unfortunately doesn't solve the problem yet for Firefox extensions. Don't know how to reliably detect that though.

@ShishKabab
Copy link

We've worked around it in our Firefox extension with the following code (using 7.6.1-canary.af162f9), because we have to release a fix right now:

const firebaseUtil = require('@firebase/util')
if (firebaseUtil.isReactNative) {
    firebaseUtil.isReactNative = () => true
}

That's obviously not something that'll hold up for long :) Any ideas on how to reliably detect an FF extension with <all_urls>? Would be happy to contribute a fix.

@mikelehen
Copy link
Contributor

Just poking around, I wonder if typeof extension !== 'undefined' would work to detect we're in a browser extension (https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/extension).

This may be over-broad (will likely detect any Firefox, Chrome, etc. extension), but that's probably okay. Can you verify that works and either let me know or submit a PR? Thanks!

@klaussner
Copy link

I haven't tried it but maybe a combination of runtime.getBrowserInfo and permissions.contains could also work.

@ShishKabab
Copy link

Just did a quick test, seems like it may work:
Screenshot_20200107_121803

@ShishKabab
Copy link

ShishKabab commented Jan 8, 2020

I tried to prepare a PR, but we'd need to check the result of the browser.permissions.getAll() promise in the openStream method of WebChannelConnection, which is currently not returning a promise. How should we go about this?

Also, I didn't do an npm install yet, but in case there's no typings present for the browser object, should I add them to the project, or just cast window to any and work from there?

@mikelehen
Copy link
Contributor

mikelehen commented Jan 13, 2020

@ShishKabab Thanks for the investigation. I think I'll probably err on the side of being more general and just try to detect that we're in any Firefox extension.

Per #2528 it sounds like Chrome 80+ extensions are hitting the same sort of issue, so I think I'll probably make a PR today that:

  • Detects Firefox extensions (via typeof browser === 'object' && browser.runtime)
  • Detects Chrome extensions (via typeof chrome == 'object' && chrome.runtime)

If anybody knows of any problems / limitations with that approach, let me know.

@scottfr
Copy link

scottfr commented Jan 14, 2020

Thank you for these suggestions Mike. I have patched the build of Firestore in our extension to simply delete the setting of request.httpHeadersOverwriteParam = '$httpHeaders'.

This appears to resolve the issue.

We are on Firebase 6.2.4 and would prefer to not rush out an upgrade to the newest Firebase SDK without a lengthier testing process. Will this small request.httpHeadersOverwriteParam = '$httpHeaders' removal cause any issues on older versions of Firestore?

In regards to your specific suggested detection logic, "typeof chrome == 'object' && chrome.runtime" does evaluate to truthy in Chrome Extensions but it also evaluates to truthy in regular webpages on Chrome. This https://stackoverflow.com/questions/7507277/detecting-if-code-is-being-run-as-a-chrome-extension says you should be checking for chrome.runtime.id too.

======

Stepping back, I think the backend issue should be a high priority to be fixed as quickly as possible. This is not Firestore's fault, but previously working Firestore integrations are going to break when these changes roll out in Chrome.

Chrome Extension reviews by Google can take up to 30 days or longer. So even if we submitted a fix today, it may not reach our users before Chrome 80.

@mikelehen
Copy link
Contributor

@scottfr Thank you! Good catch about my check accidentally detecting normal chrome too! I've updated it to use id as you suggested and it seems to work reliably in Chrome and Firefox now.

As per your question, it should be completely safe to remove request.httpHeadersOverwriteParam = '$httpHeaders' so you can move forward with that as a manual fix.

And thanks for highlighting the impact that this is going to have once Chrome rolls out their changes. I'd definitely love to get the backend fixed sooner, but realistically this is challenging. I've started some internal discussion to see what we can do though. Thanks for your diligence in reporting this issue!

@scottcrossen
Copy link
Contributor

This looks like #1491 fixed the issue. If this is still ongoing then please reopen the issue.

@developius
Copy link

@scottcrossen is #1491 a typo? That's this issue - not the fix?

@scottcrossen
Copy link
Contributor

Oh yeah you're right. sorry! I meant

#2534

@Hishmad
Copy link

Hishmad commented May 8, 2020

Hi there,
I had the same problem when using Angular 8 with Firebase 7.8.1.

So I made an update for the angular CLI to 9 to use it with firebase 7.8.1.

and it works.

@firebase firebase locked and limited conversation to collaborators Jun 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.