Description
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)"
}