WCF RIA Services Authorization - wcf

Assume we have two groups "Admins" and "Users". Admins are able to use any operation available in the service but the users can only use some of them.
Should I add the "Admins" group to every single operation or if I just write it on top of the class will do the trick?
Thanks.

Multiple RequiresRole attributes are combined with an AND while multiple roles passed to a single attribute are OR'd. In your case, you'll want to OR the attributes ("User" or "Admin") so you'll have to apply "Admin" to every single method.
// "Admin" && "User", equivalent to using a class attribute for "Admin"
[RequiresRole("Admin"), RequiresRole("User")]
// "Admin" || "User"
[RequiresRole("Admin", "User")]

I had the same problem. Unfortunately you have to set the roles on every method. Alternatively you can use saf-framework to implement acces based authorization.
Otherwise, I would suggest you overwrite the BeforeSubmit() method of you domain service, and check access for your objects there to avoid excessive attributes on each method.
For example you may want to change your access strategy and you don't want to go through every single method and do that.

Related

ASP.NET Core Identity - NormalizedUserName, NormalizedEmail

While developing a multi-tenant app with ASP.NET Core I noticed that it brings 2 new indices: NormalizedUserName & NormalizedEmail.
The main problem is that it gets too difficult to have a unique user per tenant.
What I mean is having multiple users with the same UserName & Email but different TenantID.
In order to achieve this I have to remove those indices
public static void RemoveIndexes(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<ApplicationUser>(entity =>
{
var normalizedUserNameIndex = entity.HasIndex(u => new { u.NormalizedUserName }).Metadata;
entity.Metadata.RemoveIndex(normalizedUserNameIndex.Properties);
var normalizedEmailIndex = entity.HasIndex(u => new { u.NormalizedEmail }).Metadata;
entity.Metadata.RemoveIndex(normalizedEmailIndex.Properties);
});
}
My questions are:
What is the purpose of these 2 new indices?
What would it affect if we just remove them?
Is there anything we need to pay close attention to after removing them? (e.g. overriding default UserManager functionality or something to that effect)
First of all, I wouldn't change anything of the Identity Framework if I can't oversee the effects. If you insist, you can test what happens yourself. But, do you need to remove the fields?
If the relation of user-to-tenant is one-to-many, then tenantId should not be a field of ApplicationUser but rather be stored in a seperate table, like UserClaims.
You can add multiple tenantId's as claim of the same type, like http://tenant.company.com/Id. It will then become a collection of values, like what happens with roles.
If you don't want this then you can use different claimtypes, like http://tenant.company1.com/Id, http://tenant.company2.com/Id or something like that.
You can choose to include only claims that are linked to the tenant, which could be determined from the site binding or the url, for instance.
This design allows the user to login using the same password everywhere. Please note, this is about identity: who is the user? The user doesn't need to have a different password for every tenant.
It also makes it easier to change a password. Because I wonder, how does your scenario look like with multiple user records for each tenant? Will you update all records at once when a password changes? And how will you support 'forgot password' and other features?

customizing simple membership to use existing tables

I have a User table in my repository pattern database and I am looking to connect the Roles. What is the best way to customize simple membership?
Read the following MSDN articles:
Implementing a Membership Provider
Implementing a Role Provider
and the following CodeProject article:
Custom MembershipProvider and RoleProvider Implementations that use Web Services
You should set your configuration in InitializeSimpleMembershipAttribute.cs file located into the Filters folder of your project.
Open that file and find the following line:
WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile",
"UserId",
"UserName",
autoCreateTables: true);
Now, you just need to put your connection string to your database(must be declared into web.config) into the first parameter, table name into the second parameter, UserId column name into the 3th param. and UserName column name into the 4th param.
About the last param, if you set it to true, if simple membership doesn't find any of the required table into your database, it'll create them.
However, I recommend you that you use separate tables for simple membership and let SM create its own tables. After that, you can add all your existing users to the SM tables by a block of code like the following, once for ever:
var oldUsers = db.Users.ToList();
foreach (User u in oldUsers)
{
WebSecurity.CreateUserAndAccount(u.UserName, u.Password);
}
And after that, you haven't problems with the membership and authorization jobs any more...

yii rbac: check autorizations on groups instead of users

I have a question about the rbac system. I think I've pretty well understood it but I need more informations about a special case.
I would like to do the autorisations on groups instead of users. I mean for instance the group "HR" has permission to create a person. Then any person who join this group would have it as well.
Let me give you more informations.
A part of my database:
And this a part of what my group hierarchy could be:
So what I'm looking for, this would be a must, is a system where each group has some autorizations. People get the autorizations of their group and of their parents group (for instance people in "Forsys" has the autorizations of "Forsys", "R&D" and "Administration").
The solution I see at the moment is using bizrule. But I'm not sure write php code in database is a good idea and then if I update the group hierarchy (R&D inherits of RH instead of Administration) I would have to modify bizrule in database. I tried it and it works well but as you can see it require a lot of code.
$user = User::model()->with("people","people.groups")->findByPk(Yii::app()->user->id);
foreach($user->people[0]->groups as $group)
if($group->id == 2)
return true;
return false;
It's just for see if a user is in a group (without checking parent groups and hierarchy)
Another possibility could be create a new table "group_auth" where we would say for instance:
-Group_2 has role "managePerson"
-Group_3 has operation "deleteUser"
...
And then everytime a user is added in or removed of a group we would update his autorizations in the auth_assigment table.
I'd like to hear other opinions on this subject.
All comments will be appreciated :)
Thank you for reading and sorry for my English if you had difficulties to understand me.
Michaël S.
Do users ever get their own authorization items? If not, seems like you could in essence swap out the userid column in auth_assignment and name it / treat it as groupID instead. That way you wouldn't need to worry about keeping user auth assignments in sync with your group roles.
A couple of places you'd probably need to make some changes:
- by default CWebUser passes in the logged in userid for use in bizrules. Might be good to change that our with your own override that passes in groupId/groupIds instead.
- you'd need to override CDbAuthManager and rework some of how things work there
We've done something similar on a project I've worked on (we were handling multi-tenant RBAC custom permissions), which required custom CDbAuthManager overrides. It gets a bit tricky if you do it, but there is an awful lot of power available to you.
Edit:
Understood about your users sometimes needing to have additional authorizations. What if your group has a 'roles' field with different roles serialized in it (or some other method of having multiple roles stored for that group, could also be a relationship).
Then, on user login (for efficiency), you'd store those roles in session. Probably the easiest way to handle things would be to write a custom checkAccess for your WebUser override:
https://github.com/yiisoft/yii/blob/1.1.13/framework/web/auth/CWebUser.php#L801
as that will make things simpler to do your custom checking. Then I'd probably do something like:
if(Yii::app()->user->hasGroupAccess() || Yii::app()->user->checkAccess('operation/task/role')) {
....
}
In your WebUser hasGroupAccess method, you could loop over all group roles and send those to checkAccess as well.
Think that will work?
What I use to check access for groups when it's in another table, or somewhere else in the application I give the user the role per default. By using this:
return array(
'components'=>array(
'authManager'=>array(
'class'=>'CDbAuthManager',
'defaultRoles'=>array('authenticated', 'R&D', 'Administration'),
),
),
);
Under: Using Default Roles
By using this, every user gets these assignments. Now, I create a business rule to make sure that the checkAccess('group') will return the correct value.
For example in your case the business rule for R&D would be:
return (
count(
Person::model()->findByPk(Yii::app()->user->id)->groups(array('name'=>'R&D'))
) > 0
) ? true : false;
So what this does is:
find the logged-in person by primary key
look into groups (from the user) for the group with name R&D
if there is a group: return true (else return false)

In Rails 3, is there a difference between = and assign_attributes?

Let's say you're in your user controller and you want to change the name a #user based on some params you have available to you.
I want to know if there is any difference between the following:
#user.name = params[:user][:name]
or
#user.assign_attributes({:name=> params[:user][:name]})
Thanks in advance!
A great way to figure out questions like this is to dive into the source. I found the method in activerecord/lib/active_record/attribute_assignment.rbCheck it out here.
The assign_attributes method will actually just loop through the parameters given and sends the :name= message to your model. However, because you are possibly assigning many attributes, it takes into account mass-assignment precautions. (ie. make sure that the attribute is listed as attr_accessible).
The = (e.g. #user.name = params[:user][:name]) directly calls the attribute setter with no security check. The assign_attributes checks security for the values passed in.
From the Rails API for assign_attributes:
Allows you to set all the attributes for a particular mass-assignment
security role by passing in a hash of attributes with keys matching
the attribute names (which again matches the column names) and the
role name using the :as option.
Source for assign_attributes

How to check the user's CRUD permissions for an object in Salesforce?

According to a requirement, i have to change the owner of an account if the user does not have read access to a third object.
I need a functionality similar to the isAccessible() method of Describe Field Result, but it is only available for the current logged in user.
Is there any other way to check the user's CRUD permissions for an object in Apex code?
I wrote an article about this on my blog. There is a feature that was just released in version 24.0 of the API (Spring Release) that will let you do just this on a record by record basis for the current user.
Here is the link to that blog entry that goes into details: How to tell if a user has access to a record
Don't confuse record level access with CRUD - the latter is the ability for a user to Create, Read, Update or Delete an object in general, regardless of sharing rules etc. that might affect the user's access to a particular record.
To check whether a user can create (e.g. Contacts) in general, just use
Schema.sObjectType.Contact.isCreateable()
(returns true or false)
From the documentation. it sounds like you want to use execute anonymously.
Apex generally runs in system context; that is, the current user's permissions, field-level security, and sharing rules aren’t taken into account during code execution.​ The only exceptions to this rule are Apex code that is executed with the executeAnonymous call. executeAnonymous always executes using the full permissions of the current user. For more information on executeAnonymous, see Anonymous Blocks.
Although Apex doesn't enforce object-level and field-level permissions by default, you can enforce these permissions in your code by explicitly calling the sObject describe result methods (of Schema.DescribeSObjectResult) and the field describe result methods (of Schema.DescribeFieldResult) that check the current user's access permission levels. In this way, you can verify if the current user has the necessary permissions, and only if he or she has sufficient permissions, you can then perform a specific DML operation or a query.
For example, you can call the isAccessible, isCreateable, or isUpdateable methods of Schema.DescribeSObjectResult to verify whether the current user has read, create, or update access to an sObject, respectively. Similarly, Schema.DescribeFieldResult exposes these access control methods that you can call to check the current user's read, create, or update access for a field. In addition, you can call the isDeletable method provided by Schema.DescribeSObjectResult to check if the current user has permission to delete a specific sObject.
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_classes_perms_enforcing.htm#kanchor431
Have you tried the runAs() method?
Something like (not verified):
User u = [SELECT Id FROM User WHERE Name='John Doe'];
System.runAs(u) {
if (Schema.sObjectType.Contact.fields.Email.isAccessible()) {
// do something
}
}
The DescribeSObjectResult class has methods for checking CRUD.
E.g. this allows you to test whether or not the current user can update the account object in general.
Schema.DescribeSObjectResult drSObj = Schema.sObjectType.Account;
Boolean thisUserMayUpdate = drSObj.isUpdateable();
#John De Santiago: your article covers record level access rather than object CRUD (= object level access)
Very old post. Since then SF add option to query object permission:
Select SobjectType ,ParentId, PermissionsEdit, PermissionsRead
From ObjectPermissions
Order by ParentID, SobjectType ASC
Basically you will need to get the profile and permissionset of the user that you want to check and the relevant object. So it will be something like:
Select SobjectType ,ParentId, PermissionsEdit, PermissionsRead
From ObjectPermissions
where parentId IN :UserProfileIdAndPermission
AND sObjectType=:objectType
Order by ParentID, SobjectType ASC