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.
Related
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.
As shown below, I want to set up a security rule when a user exists in the "users" node, the user can access the "email" node. Meeting the case, I used builtin exists() function but it doesn't seem working correctly. I've just been getting "Missing or insufficient permissions." Just in case, the user exists under the "users" node for sure.
This issue still occurs when using the get() function, where incorporating this issue(Firestore security rule get() not work)
I'm totally not sure why this rule doesn't work. Would be appreciated if you could give me any help.
service cloud.firestore {
match /databases/{database}/documents {
match /emails/{email} {
allow read, write: if exists(/databases/$(database)/documents/users/$(request.auth.uid));
}
match /users/{userId} {
allow read, write: if request.auth != null;
}
}
}
Did you try use get() instead of exists()?
For me this is working
allow read, write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data != null
When you creating signIn options, you also should set "requestIdToken" to options builder to then use it in Firestore Rules like "request.auth.uid":
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
When you get GoogleSignInAccount(for example) in your activity's onActivityResult, then you have to set it to Firestore singleton instance:
private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount) {
AppState.googleAccount = acct
val mAuth = FirebaseAuth.getInstance()
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, object : OnCompleteListener<AuthResult> {
override fun onComplete(#NonNull task: Task<AuthResult>) {
when (task.isSuccessful) {
true -> // good, continue from this line
false -> showError("error sign in with google account")
}
}
})
}
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.
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.');
}
}
});
Any ideas on how can I list all the activities in my domain by using the new google+ domain's API in java?
The Developers' Live video shows at 4:00 minute mark that you can do something like this:
Plus.Activities.List listActivities = plus.activities().list("me", "domain");
The Link for this code is here.
But when I actually run the same line of code it shows me the following error.
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"location" : "collection",
"locationType" : "parameter",
"message" : "Invalid string value: 'domain'. Allowed values: [user]",
"reason" : "invalidParameter"
} ],
"message" : "Invalid string value: 'domain'. Allowed values: [user]"
}
The error makes sense as in the activities.list documentation it says that "user" is the only acceptable value for collection and not "domain."
So what should I do about this issue?
As you say, the only available way is to list posts by the currently logged user. You have to use user delegation (with service accounts) and loop over all users in the domain in order to get all published activities.
You can use the updated field on the response to check if there is anything new in a user's list of activities.
This line of thought applies to the whole Domains API: every operation is done on behalf of a user, there is no "admin" account with superpowers. This can be a limitation when acting on a big number of users, as you are forced to authenticate for each one in turn (if someone has an idea on how to achieve this in a more efficient way, please share!)
As the documentation sais, only "public" is allowed:
https://developers.google.com/+/api/latest/activities/list
However even using the code provided in the example in the API doc, after going through successful authentication I get 0 activities.
/** List the public activities for the authenticated user. */
private static void listActivities() throws IOException {
System.out.println("Listing My Activities");
// Fetch the first page of activities
Plus.Activities.List listActivities = plus.activities().list("me", "public");
listActivities.setMaxResults(100L);
// Pro tip: Use partial responses to improve response time considerably
listActivities.setFields("nextPageToken,items(id,url,object/content)");
ActivityFeed activityFeed = listActivities.execute();
// Unwrap the request and extract the pieces we want
List<Activity> activities = activityFeed.getItems();
System.out.println("Number of activities: " + activities.size());
// Loop through until we arrive at an empty page
while (activities != null) {
for (Activity activity : activities) {
System.out.println("ID " + activity.getId() + " Content: " +
activity.getObject().getContent());
}
// We will know we are on the last page when the next page token is null.
// If this is the case, break.
if (activityFeed.getNextPageToken() == null) {
break;
}
// Prepare to request the next page of activities
listActivities.setPageToken(activityFeed.getNextPageToken());
// Execute and process the next page request
activityFeed = listActivities.execute();
activities = activityFeed.getItems();
}
}
Anybody know how to get this to work?
when you use Google+ API you must use "public" but when you use Google+ Domains API you must use "user" parameter value.