How can I prevent hacking like $remove in AngularFire - angularfire

All:
I am pretty new to AngularFire, when I follow tutorial to do a simple todo app, I wonder how can I only allow user to add new todo, but not delete. Basically I do not want client side hack to destroy my data. Like user opens console and manually call $remove API, how can I prevent that?
Thanks

To prevent clients from performing unwanted CRUD operations on your Firebase database, you need to define database rules.
Rules are defined in a JSON structure and can reference the current auth information. For example, if you are storing user information in database under /users/<uid>, the following rule would grant each user read/write access to their own information and read access to other users' information:
{
"rules": {
"users": {
".read": "auth != null"
"$uid": {
".write": "auth != null && auth.uid == $uid"
}
}
}
}
Rules can also reference data that's already in the database, so it's possible to allow writes only if there is no existing data at a particular key - that is, you can prevent updates.
Similarly, rules can reference the new data that is to be stored, so it's possible to check that new data has been specified - that is, you can prevent deletes.
A rule like this would allow todos (stored under /todos/<uid>/<todoId>) to be created, but neither updated nor deleted:
...
"todos": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
"$todoId": {
".write": "auth != null && auth.uid == $uid && data.val() == null && newData.val() != null"
}
}
}
...
Maintaining rule definitions in the JSON structure can become difficult; you might find Firebase's Bolt tool useful for defining more complicated rules.

Related

How to detect if security rules are preventing me connecting to auth() in rn-firebase?

How can I figure out if I'm in an error state and that's why the onUserChanged() returned user was null?
My app is still in development and uses React-Native and Firebase. My security rules are still in test mode, but recently expired:
allow read, write: if
request.time < timestamp.date(2023, 2, 3);
}
In my main App.tsx I have a useEffect like this that gets the current user and, if there isn't one, signs the user in anonymously:
const currentUserRef = useRef<FirebaseAuthUser | null>();
useEffect(() => {
const unsubscribe = auth().onUserChanged((user: FirebaseAuthUser | null) => {
if (user !== currentUserRef.current) {
if (user !== null) {
// Set up current user stuff
} else {
// signInAnonymously
}
}
}
Now my code is hanging here. We get a null user but currentUserRef is also null, so nothing happens.
The device I'm developing on does have an account which should be returned here so I'm guessing this is related to my security rule expiration. I could just attempt to sign the user in anonymously in this current case and maybe that would give me the error info I'm seeking, but I'm wondering if there's some other way to get this information

Firebase Storage security rules playground "Simulated read denied"

I want my user to be able to read and write only his own data but. When I test the rules, I get the message "Simulator read denied". Please tell where i am wrong? Thanks for your time.
Here the some information :
RULES
service firebase.storage {
// Only a user can upload their file, but anyone can view it
match /users/{userId}/{fileName} {
allow read ;
allow write: if request.auth != null && request.auth.uid == userId;
}
}
LOCATION
/b/online-notepad-d43d2.appspot.com/o/WkqtgpdUYRUGOBaAfmCByXtVPoT2/file1.txt
PROVIDER
"password"
FIREBASE UID
WkqtgpdUYRUGOBaAfmCByXtVPoT2
EMAIL
hgaur701#gmail.com
EMAIL VERIFIED
true
Authentication payload
{
"uid": "WkqtgpdUYRUGOBaAfmCByXtVPoT2",
"token": {
"sub": "WkqtgpdUYRUGOBaAfmCByXtVPoT2",
"aud": "online-notepad-d43d2",
"email": "hgaur701#gmail.com",
"email_verified": true,
"firebase": {
"sign_in_provider": "password"
}
}
}
SCREENSHOT
exact location i am using : "/WkqtgpdUYRUGOBaAfmCByXtVPoT2/file1.txt"
and one more thing i upload this folder and file from upload button.
not from POST request.
STILL GETTING SAME RESULT :(
Here you define two completely separate clauses:
allow read ;
allow write: if request.auth != null && request.auth.uid == userId;
So you have an empty read clause, and a non-empty write clause.
You probably want to use:
allow read, write: if request.auth != null && request.auth.uid == userId;
Edit for second problem: as you said in your edit, you are accessing the path /WkqtgpdUYRUGOBaAfmCByXtVPoT2/file1.txt, but your rules only define access permissions for match /users/{userId}/{fileName}. Since you are only allowing access in /users/... and the path you try to use is not in /users, the access is denied by the rules.

How can I write a "If..then" condition in Axiomatics

The decisioning is to permit if the user has required roles. The required roles and the user's current permissions are in JSON format.
Required permissions: (Saved as a attribute)
{
"data": {
"service1": {
"service1.1": true
},
"service2": {
"service2.1: false,
"service2.2": true,
"service2.3": false
}
}
}
User's current permissions:
{
"data": {
"service1": {
"service1.1": true
},
"service2": {
"service2.1: false,
"service2.2": false,
"service2.3": true
}
}
}
To make the decision, we need to check if the user has the services as true similar to required Permissions. In the above example, the user has data.service1.service1.1 as true and data.service2.service2.3 as true where the required roles being data.service1.service1.1 as true and data.service2.service2.2 as true, in this case we deny.
I wrote separate rules to check for each and every service, but that would only be a check of combination of services.
rule service1.1{
permit
condition
(allOf(function[booleanEqual], true, requiredRoles.data.service1.service1.1))
&&
(allOf(function[booleanEqual], true, requiredRoles.data.service1.service1.1))
on permit {
advice reasonForPermit{
reasonAttribute= "Contains Valid services"
}
}
}
Would someone please help on how to write a if.. then check in alfa?
There is no if..then construct in ALFA (or XACML). You use combining algorithms instead. In particular, onPermitApplySecond is the policy combining algorithm that resembles an if..then construct the most.
However, there is usually a simpler way to express what you want if you can make reasonably assumptions on your attribute data. In your example, for instance, if it's always guaranteed that both the required and current permissions contain exactly one boolean value for each available service, then you could write:
rule {
target
clause requiredRoles_service1_1 == false or permitted_service1_1 == true
clause requiredRoles_service2_1 == false or permitted_service2_1 == true
...
permit
}
Remember that in a target, clauses are AND'ed together. This rule then checks that, for every service, the role is either not required or is given in the current permissions.
If instead it may happen than any of those attributes is not present (i.e. there are no values for the attribute), then you have to guard against that case. You can do that using a condition like the following one, but there are other ways too:
rule {
permit
condition
(not(booleanIsIn(true, requiredRoles_service1_1)) || booleanIsIn(true, permitted_service1_1))
&&
(not(booleanIsIn(true, requiredRoles_service2_1)) || booleanIsIn(true, permitted_service2_1))
&&
...
}
All in all, there are usually simpler ways to express a policy if you can massage attribute data into other forms. Having a pair of attributes per service, like in the examples above, may not be necessary.
If you could gather all required roles and current permissions in one attribute each, then the policy can be expressed much more compactly. Let's say you have two attributes, requiredRoles and permittedRoles whose values list the service roles required and permitted for a given user, respectively. In your example, this would mean that requiredRoles has value, say, ["service1.1", "service2.2"] and permittedRoles has value ["service1.1", "service2.3"]. Then you can write a rule like this:
rule {
permit
condition stringSubSet(requiredRoles, permittedRoles)
}
I was able to do this by creating separate attributes for each service and wrote a rule with the target clause with the service from required roles and the condition will be if the service in the permitted role is true. I combined all the rules as below in the policy using permitunlessDeny algorithm
rule rule1 {
target clause requiredRoles.service1_1 == true
deny
condition
not(permittedRoles.service1_1 == true)
on permit {
advice reasonForPermit {
reasonAttribute= "User has valid services"
}
}
}
Thank you for the suggestion Pablo.

Parse.com procedure for validating password requirements in Parse.Cloud.beforeSave(Parse.User

I am trying to find the best procedure for adding password requirements with Parse.com. It appears the easiest way would be to use a cloud function to execute right before user data is saved. My only caveat is that I want to validate user passwords only when the password is different from what is stored in the db or if the user does not exist in the db.
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
...
}
Couple of questions:
Does request.object.existed() work in beforeSave functions as it does with afterSave?
Can I access the user's password (using Parse.Cloud.useMasterKey()) via the request.object in the beforeSave functions? Or do I need to query the user's object inside the function.
In the log the input to the beforeSave function appears to have original and updated keys similar to the json below. However, I was not able to access the original and update json through the request.object. How would I access this data? It would be nice if the only check needed to be performed to verify whether a user's password as changed if a comparison between request.object.original.password !== request.object.updated.password
Sample cloudcode log output:
Input: {"original":{"email":"blah",
"firstname" : "blah",
"emailVerified":true,
"username":"blah",
"createdAt":"2014-04-28T23:05:47.452Z",
"updatedAt":"2014-0716T01:55:52.907Z",
"objectId":"blah",
"sessionToken":"blah"},
"update":{"firstname":"blah2"}}
Try something like this:
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
if (request.object.isNew()) {
// new object..
response.success();
} else {
if (request.object.dirtyKeys().indexOf("password") > -1) {
// Attempted to change the password.
response.error('No.');
}
}
});

Updating complex type with ef code first

I have a complex type called account, which contains a list of licenses.
Licenses in turn contains a list of domains (a domain is a simple id + url string).
In my repository I have this code
public void SaveLicense(int accountId, License item)
{
Account account = GetById(accountId);
if (account == null)
{
return;
}
if (item.Id == 0)
{
account.Licenses.Add(item);
}
else
{
ActiveContext.Entry(item).State = EntityState.Modified;
}
ActiveContext.SaveChanges();
}
When I try to save an updated License (with modified domains) what happens is that strings belonging straight to the license get updated just fine.
However no domains get updated.
I should mention that what I have done is allow the user to add and remove domains in the user interface. Any new domains get id=0 and any deleted domains are simply not in the list.
so what I want is
Any domains that are in the list and database and NOT changed - nothing happens
Any domains that are in the list and database, but changed in the list - database gets updated
Any domains with id=0 should be inserted (added) into database
Any domains NOT in the list but that are in the database should be removed
I have played a bit with it with no success but I have a sneaky suspicion that I am doing something wrong in the bigger picture so I would love tips on if I am misunderstanding something design-wise or simply just missed something.
Unfortunately updating object graphs - entities with other related entities - is a rather difficult task and there is no very sophisticated support from Entity Framework to make it easy.
The problem is that setting the state of an entity to Modified (or generally to any other state) only influences the entity that you pass into DbContext.Entry and only its scalar properties. It has no effect on its navigation properties and related entities.
You must handle this object graph update manually by loading the entity that is currently stored in the database including the related entities and by merging all changes you have done in the UI into that original graph. Your else case could then look like this:
//...
else
{
var licenseInDb = ActiveContext.Licenses.Include(l => l.Domains)
.SingleOrDefault(l => l.Id == item.Id)
if (licenseInDb != null)
{
// Update the license (only its scalar properties)
ActiveContext.Entry(licenseInDb).CurrentValus.SetValues(item);
// Delete domains from DB that have been deleted in UI
foreach (var domainInDb in licenseInDb.Domains.ToList())
if (!item.Domains.Any(d => d.Id == domainInDb.Id))
ActiveContext.Domains.Remove(domainInDb);
foreach (var domain in item.Domains)
{
var domainInDb = licenseInDb.Domains
.SingleOrDefault(d => d.Id == domain.Id);
if (domainInDb != null)
// Update existing domains
ActiveContext.Entry(domainInDb).CurrentValus.SetValues(domain);
else
// Insert new domains
licenseInDb.Domains.Add(domain);
}
}
}
ActiveContext.SaveChanges();
//...
You can also try out this project called "GraphDiff" which intends to do this work in a generic way for arbitrary detached object graphs.
The alternative is to track all changes in some custom fields in the UI layer and then evaluate the tracked state changes when the data get posted back to set the appropriate entity states. Because you are in a web application it basically means that you have to track changes in the browser (most likely requiring some Javascript) while the user changes values, adds new items or deletes items. In my opinion this solution is even more difficult to implement.
This should be enough to do what you are looking to do. Let me know if you have more questions about the code.
public void SaveLicense(License item)
{
if (account == null)
{
context.Licenses.Add(item);
}
else if (item.Id > 0)
{
var currentItem = context.Licenses
.Single(t => t.Id == item.Id);
context.Entry(currentItem ).CurrentValues.SetValues(item);
}
ActiveContext.SaveChanges();
}