How do I write a Firebase security rule where unauthenticated users can write but only my trusted server can read? - firebase-security

I would like to write a rule where persons submitting a form from the webpage (unauthenticated) can .write and only the server can .read messages that are newer than two minutes old.
The server (App Engine Python-Flask instance) polls Firebase every two minutes., but I keep getting a JSON feedback {error: Permission Denied}, instead of my requested data.
The Security Rules look like this:
{
"rules": {
"leads": {
".write": true,
"$user_id": {
".write": true,
".read": "auth !== null && $user_id === auth.uid && data.child('CREATED').val() > (now - 120000)"
}
}
}
}
The simulator tells me:
Attempt to read /leads with auth={"provider":"custom","uid":"lead_checker"}
/
/leads
No .read rule allowed the operation.
Read was denied.
Can anyone spot what I am doing wrong or provide a suitable replacement?

When you have a clause like $user_id === auth.uid in your read rule, it says: this data can be read when the current user's uid matches the node name. So for your user lead_checker is means that it can read the node named lead_checker.
What you're probably looking to do is to allow lead_checker read access to each user node:
{
"rules": {
"leads": {
"$user_id": {
".write": true,
".read": "auth.uid == 'lead_checker'"
}
}
}
}
With this the lead checker can reach each node under leads. Note that it still can't read the leads node itself. If that is needed, move the read rule one level up:
{
"rules": {
"leads": {
".read": "auth.uid == 'lead_checker'"
"$user_id": {
".write": true,
}
}
}
}

Related

In freeradius, is there a way to refer to LDAP attributes in post-auth section?

We're using PEAP with mschapv2 using ntlm command line. We want to assign users ip's from LDAP
After we get a reply back from ActiveDirectory, we're doing an authorization check by binding to LDAP and looking at their groups:
post-auth {
if (network-auth-LDAP-Group == "xxxcompany-vpn") {
noop
} else {
reject
}
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
We'd like to pull 10.1.2.3 from an LDAP Attribute. We tried doing what the documentation says by putting this in the LDAP config:
update {
reply:Framed-IP-Address := 'radiusFramedIPAddress'
}
In LDAP, we imported the schema and set radiusFramedIPAddress on the user to 10.1.2.3
However, we can't see the Framed-IP-Address value being updated in the log.
We'd like to set Framed-Ip-Address on the reply:
post-auth {
if (network-auth-LDAP-Group == "xxxcompany-vpn") {
update reply {
Framed-Ip-Address := 10.1.2.3
}
} else {
reject
}
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
That works however ^ Is there a way to refer to LDAP attributes in the post-auth section? Something like this?
post-auth {
if (network-auth-LDAP-Group == "xxxcompany-vpn") {
update reply {
Framed-Ip-Address := %{ldap:'radiusFramedIpAddress'}
}
} else {
reject
}
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}

How to synchronize Azure Mobile Services Offline Sync from an Xamarin app

previously, there was the possibility of creating an app services in azure that allowed you to connect an SQL database through the creation of "Easy Tables" but this will be deleted on November 11 (https://aka.ms/easydeprecation), but you can no longer add more tables this way, but you have to do it by the App Service Editor (preliminary version).
I can create the table as the link attached says, the problem is that when I synchronize my data from my xamarin app it says that the resource does not exist or has been removed, that it has been changed or that it is temporarily unavailable.
I think the problem is some configuration or package or extension that I must install in this new app services but I cannot identify it.
My code C #
public async Task SyncAllAsync(bool SyncForce = false)
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
long PendingChanges = CurrentClient.SyncContext.PendingOperations;
try
{
await CurrentClient.SyncContext.PushAsync();
await PatientTable.PullAsync("SyncPatientAsync", PatientTable.CreateQuery());
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
// Simple error/conflict handling. A real application would handle the various errors like network conditions,
// server conflicts and others via the IMobileServiceSyncHandler.
if (syncErrors != null)
{
foreach (MobileServiceTableOperationError error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
//Update failed, reverting to server's copy.
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change.
await error.CancelAndDiscardItemAsync();
}
string message = "Error executing sync operation. Item: " + error.TableName + " (" + error.Item["id"] + "). Operation discarded.";
Debug.WriteLine(message);
}
}
}
Patient.json
{
"softDelete" : true,
"autoIncrement": false,
"insert": {
"access": "anonymous"
},
"update": {
"access": "anonymous"
},
"delete": {
"access": "anonymous"
},
"read": {
"access": "anonymous"
},
"undelete": {
"access": "anonymous"
}}
Patient.js
var table = module.exports = require('azure-mobile-apps').table();
// table.read(function (context) {
// return context.execute();
// });
// table.read.use(customMiddleware, table.operation);
The Easy Tables is just a Web API - each table is at https://yoursite.azurewebsites.net/tables/yourtable and the pull operation basically does something like GET https://yoursite.azurewebsites.net/tables/yourtable?filter=(UpdatedAt ge datetimeoffset'some-iso-date'). Enable logging on your Xamarin host (details here plus the end of the same file) to see the actual HTTP requests that are happening.
The error you are receiving is probably a 404. Common issues:
You specified http instead of https in the client
The name of the table is wrong

firebase rules: does user have right to see document

I am trying to write some rules to allow users to access only the documents they have the rights to.
I have two collections: a "travels" and a "users" collection.
The "travels" collection has several travels (documents) with names "001", "002", "003", ...
The users collection has users (documents) with names "user1#mail.com", "user2#mail.com",...
Inside each user there is an Object (map) called "allowedTravels", in which i keep track of which travels that user can see. Something like this:
travels: {
001: {
name: 'Nice travel'
},
002: {
name: 'Amazing Trip'
}
}
users: {
user1#email.com: {
allowedTravels: {
001: {
hasPayed: true
}
}
},
user2#mail.com: {
allowedTravels: {
001: {
hasPayed: false
},
002: {
hasPayed: true
}
}
}
}
What i want is to allow users to access the travel documents only if they have access to them, in this case user1 should have access to travel 001, and user2 should have access to travel 001 and 002.
What i want to check is if inside the users document, in the allowedTravels object there is a property with the name of the "travel document". If so: allow, if not: deny
At the moment my rules look like this:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if isSignedIn();
}
}
function isSignedIn() {
return request.auth.uid != null;
}
}
What i have tried was something like this:
match /{document} {
return exists(/users/${request.auth.email}/allowedTravels/{document})
}
What would be the correct way to achieve what i am looking for?
I appreciate any help you can give me. thanks!

Error while using Paginated Lucene Search in cloudant

I'm currently having an issue in lucene cloudant implementation with pagination.
{"error":"scala.Symbol cannot be cast to org.apache.lucene.util.BytesRef","reason":null}
The URL that I am trying to access :
/_design/contact/search/name?q=name%3Asa%2A+OR+default%3Asa%2A&limit=10&bookmark=g1AAAAEPeJzLYWBgYMlgTmGQTUlKzi9KdUhJMtMrzsnMS9dLzskvTUnMK9HLSy3JASpjSmRIsv__38WmJPCwJJXmpOTGJeFqtscl-4kByCZVI9hQDyaAaa4DMhjAZIMDUAKaMZ-VEMyiXUFxJADEEPQXOKTlQUASZpV2Q&stale=ok&sort="name<string>"
What I found :
If I remove the bookmark ( means 1st page ) it works fine.
Or, If I remove the sort, it works fine.
below is the index that I created for this view :
"indexes": {
"name": {
"index": "function (doc)
{
if (doc.Type == 'contact')
{
index("default", doc._id);
index("name",doc.Name,{"store": "yes"});
if(doc.Profile) {index("profile", doc.Profile, {"store": "no"});}
if (doc.Aliases)
{
if (Array.isArray(doc.Aliases))
{
doc.Aliases.forEach(function (alias){
index("alias", alias, {"store":"yes"})
})
}
else
{
index("alias", doc.Alias_Name, {"store":"yes"})
}
}
}
}"
}
}
We have deployed a fix for this issue and you should no longer be experiencing this problem. Please confirm that that is the case. Thanks!

How to execute code before store configuration takes effect?

In our app we rely on the sessionStorage for persistence. However on mobile Safari the sessionStorage is not available when browsing in private mode.
However, for those customers using Safari in private mode it's ok to switch to an in-memory approach. Our app continues to be usable to some extend (you will lose data when you refresh the browser but since it's a single page application you never have to refresh anyway).
The fix was quite easy to do in development mode. However, after running a production build I faced a huge problem.
So, code is worth a thousand words. Here is what we currently use:
index.html
//...
<script type="text/javascript">
var isSessionStorageAvailable = true;
var storage = window.sessionStorage;
if (typeof window.sessionStorage == 'undefined' || window.sessionStorage === null) {
isSessionStorageAvailable = false;
} else try {
storage.setItem('__ccTest', '__ccTest');
} catch (err) {
isSessionStorageAvailable = false;
}
</script>
<script id="microloader" type="text/javascript" src="../sencha/microloader/development.js"></script>
//...
myStore.js
Ext.define('App.store.Quote', {
extend: 'Ext.data.Store',
requires: ['App.model.QuoteItem','Ext.data.proxy.SessionStorage'],
config :{
model: 'App.model.QuoteItem',
autoLoad: true,
autoSync: true,
identifer: 'uuid',
proxy:{
type: isSessionStorageAvailable ? 'sessionstorage' : 'memory',
id:'ccCart'
}
},
//...
So, before sencha get's loaded we first check for the sessionStorage and set a global variable. So at the time when the store file loads the right configuration is picked up.
However, I really dislike this solutions as I had to alter the index.html file. In development mode you can just write this check anywhere in the app.js file because all the other files are loaded afterwards. But in production that's not the case. So I wonder how would you do that properly without altering the index.html file?
UPDATE
I also tried to use the applier like this:
applyProxy: function(proxy, oldProxy){
proxy.type = 'sessionstorage';
var storage = window.sessionStorage;
if (typeof window.sessionStorage == 'undefined' || window.sessionStorage === null) {
proxy.type = 'memory';
} else try {
storage.setItem('__ccTest', '__ccTest');
} catch (err) {
proxy.type = 'memory';
}
this.callParent([proxy, oldProxy]);
}
However, the first time some code calls sync() on this store it raises an error inside the sencha framework:
It's inside the sync method of the store class on this line (it's from the minified source, sorry):
d.getProxy().batch({operations: b,listeners: d.getBatchListeners()})
It raises an error because getProxy() returns undefined. So it seems as if the applier didn't work :(.
Use the applier...
Ext.define('App.store.Quote', {
extend : 'Ext.data.Store',
requires : ['App.model.QuoteItem', 'Ext.data.proxy.SessionStorage'],
config : {
model : 'App.model.QuoteItem',
autoLoad : true,
autoSync : true,
identifer : 'uuid',
proxy : {
id : 'ccCart'
}
},
applyProxy : function (config, oldProxy) {
config.type = isSessionStorageAvailable ? 'sessionstorage' : 'memory';
return this.callParent([config, oldProxy]);
}
});
Just create your store like so :
Ext.define('App.store.Quote', {
extend: 'Ext.data.Store',
requires: ['App.model.QuoteItem','Ext.data.proxy.SessionStorage'],
config :{
model: 'App.model.QuoteItem',
autoLoad: true,
autoSync: true,
identifer: 'uuid'
}
And then, whenever you check if sessionStorage is available, then just do
myStore.setProxy({
type: isSessionStorageAvailable ? 'sessionstorage' : 'memory',
id:'ccCart'
});
Hope this helps
Are you sure the else..try brackets aren't causing issues (JSHint was complaining)?
var isSessionStorageAvailable = true;
var storage = window.sessionStorage;
if (typeof window.sessionStorage == 'undefined' || window.sessionStorage === null) {
isSessionStorageAvailable = false;
} else {
try {
storage.setItem('__ccTest', '__ccTest');
} catch (err) {
isSessionStorageAvailable = false;
}
}