Check whether a user name is mapped to a role - asp.net-mvc

I am developing a ASP NET MVC 5 website wherein I need to provide a WebApi for a WPF client. The client needs to send user name and password for the user, and the WebApi needs to check whether the user name and password are correct and whether the user name belongs to the admin role (defined by my website).
I am using Visual Studio 2013, so for adding roles, I directly add entries into AspNetRoles and AspNetUserRoles tables using Server Explorer. (say for example, I added admin role, and mapped user1 to admin role)
I find that to check the user name and password is correct, I can use the same code as used by the login functionality in the default account controller. I am finding trouble finding an API to check user name against a role name. I am not adding roles programmatically; I just want to check whether user1 was mapped to the admin role in the AspNetUserRoles table.
Can anyone suggest how to do that ?

It is quite easy actually. You can perform checking roles at the point where the user has authenticated successfully.
Let's say that there is a user repository with the following function:
internal interface IUserReporsitory
{
bool IsUserInRole(int userId, string rolename);
}
The function then checks for the a record in the UsersRole table for the user id and the rolename.
public class UserReporsitory : IUserReporsitory
{
public bool IsUserInRole(object userId, string roleName)
{
//Query the UsersInRole tables Join the Role Table for the user with Id = userId and RoleName=roleName
}
}
The actual implementation is a matter of an SQL query to the database.

Related

Spring LDAP unable to fetch record for external record

I am exploring spring security with LDAP. I have a code like this:
String LDAP_BASE = "OU=Employees,OU=User Accounts,dc=ad,dc=mycompany,dc=com"
ldapTemplate.search(LDAP_BASE, filter.encode(),searchControls, this::myMethod,
pagedResultsDirContextProcessor);
this::myMethod is a mapper function and entity it returns is as:
#Entry(base = "OU=Employees,OU=User Accounts,dc=ad,dc=mycompany,dc=com",
objectClasses = {"person", "user", "top"})
public class User {
#Id
#JsonIgnore
private Name id;
.......}
I am facing an issue with this arrangement. If user is internal to the company, this code returns the user correctly. But if user is external, this code doesn't return any result, even though user record is there in LDAP directory.
How can I fetch users which are external to company but there in LDAP?
The base of your search is where employees are stored in the directory tree:
OU=Employees,OU=User Accounts,dc=ad,dc=mycompany,dc=com.
If you search from OU=User Accounts,dc=ad,dc=mycompany,dc=com, you should be able to find the external users, but that really depends on the structure of the LDAP directory in your company.

Securely passing data between pages

I am looking to create a new Web App that will allow the user to first enter the users id then navigate around the site based on that user's id. So, first the user would search for an ID, select that user and have options available based on that ID.
Currently I am using the Query string to store the ID, so... /AddProduct/2222.
This works fine but I'm not too sure about the security aspects. I've thought about sessions and cookies but I don't think they are suitable for this scenario. Or do I encrypt the ID for the query string?
Does anyone have any thoughts?
Thanks
Edit
I forgot to mention, the users will be authenticated and have specific permissions on each page on the site. The data is also stored in a database. So, the site will be querying and editing/adding to current data.
So basically here you seem to be afraid that some user might modify an item belonging to another user. Alright, this sentence tells us already that you have users and items in your application and that there are some roles associated to those items. And you have a mechanism to identify those users. So you are probably using some sort of authentication such as the built-in FormsAuthentication for example. So now the question becomes: how to ensure that the currently authenticated user is not modifying the product that belongs to another user.
OK, so you have items that belong to users. I suppose that this information is stored somewhere on the server, presumably a database or something. One approach I would recommend you is to write a custom authorization attribute which would check if the requested resource id actually belongs to the currently authenticated user.
For example:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized)
{
// The user is not authenticated or authorized => no need to continue further
return false;
}
// At this stage we know that the user is authorized => we can fetch
// the username
string username = httpContext.User.Identity.Name;
// Now let's fetch the id of the resource he is trying to manipulate from the request
string id = httpContext.Request["id"];
// All that's left is to verify if the current user is the owner
// of the account
return IsOwnerOfItem(username, id);
}
private bool IsOwnerOfItem(string username, string id)
{
// TODO: query the backend to perform the necessary verifications
// about whether the user has permissions to work with the resource
// pointed by the id parameter
throw new NotImplementedException();
}
}
and now all that's left is to decorate your AddProduct controller action with this custom attribute:
[MyAuthorize]
public ActionResult AddProduct(int id)
{
// if we get that far we know that the currently authenticated user
// is the owner of the resource pointed by the id parameter and we
// could proceed respectively
...
}
With this approach you don't need to be using any sessions or encrypting anything. The encryption is already built into the ASP.NET framework under the form of a Forms Authentication cookie which holds the currently authenticated username in a secure manner. This cookie cannot be manipulated -> the user cannot impersonate as another user. So once you've got the guarantee about who the current user is, all that's left to you is to perform the necessary authorization whether he can access the requested resource.

Spring Security in Grails providing authorization

A suggestion here would be deeply appreciated.
We use Spring Security domain object security to lock down access to specific objects in our Grails application. We have extended permissions as well. We use normal #PreAuthorize annotation to control access to the domain objects depending up the privileges assigned to a specific user.
In this architecture, I want for one user to be able to invite a second user to join a group. To do this, the second user receives an invitation from the first user to join a group with specific privileges. The second user can choose to accept or reject the invitation.
Given that the domain object belongs to the first user, not the second user, how could I grant access to the second user to the domain object with the privileges offered?
I have tried to hack a solution using #PreAuthorize("permitAll") on a service method just to see if that would work. While not ask secure as granting an object the privilege to set privileges to a domain object, it at least would get me going. But no joy, I continue to get "accessDenied for class" errors, presumably because the current user is the second user, not the domain object owner.
Do I need to work through the SpEL suggestion here? I barely understand how the bean resolver works unfortunately.
Edit: Even when I verify the invitation is valid at invocation Spring ACL throws an exception when the first ACE for the new user is attempted to be inserted. The exception occurs in void setPermissions(ObjectIdentity oid, recipient, Collection permissions) at the insertAce call:
void setPermissions(ObjectIdentity oid, recipient, Collection permissions) {
Sid sid = createSid(recipient)
MutableAcl acl
try {
acl = aclService.readAclById(oid)
}
catch (NotFoundException e) {
acl = aclService.createAcl(oid)
}
int deleted = 0
acl.entries.eachWithIndex { AccessControlEntry ace, int i ->
if (ace.sid == sid) {
acl.deleteAce(i-deleted)
deleted++
}
}
permissions.each {
acl.insertAce(acl.entries.size(), it, sid, true)
}
aclService.updateAcl acl
}
I assume that the access is denied because the current user (who did not exist when the invitation was issued) does not have the rights to set permissions on an object owned by another user.
You can use your Role class not only for generic roles (Admin,User, etc.), but for application specific ones as well. Simply allow the user to create a Role for a resource and then allow their invitees to be granted that role. Spring Security comes with a handy ifAnyGranted() method, which accepts a comma-delimited String of role names. At a resource entry-point simply ensure that a particular role is granted:
class Conversation{
Role role
}
class ConversationController{
def enterConversation(){
// obtain conversation instance
if(!SpringSecurityUtils.ifAnyGranted(conversationInstance.role.authority){response.sendError(401)}
}
}
The answer turned out to be using RunAs. For Grails, I did this as follows:
Create a Role specific for allowing invited users to act as an administrator in order to access a protected object. In Bootstrap, ensure this role is loaded into the SecRole domain:
def invitedRole = SecRole.findByAuthority('ROLE_RUN_AS_INVITED_USER')
if (!invitedRole) {
invitedRole = new SecRole()
invitedRole.authority = "ROLE_RUN_AS_INVITED_USER"
invitedRole.save(failOnError:true, flush:true)
}
Ensure in config.groovy that the role can change the target object:grails.plugins.springsecurity.acl.authority.changeAclDetails = 'ROLE_RUN_AS_INVITED_USER'
Enable RunAs in config.groovy
grails.plugins.springsecurity.useRunAs = true
grails.plugins.springsecurity.runAs.key = [key]
annotate the service method
#PreAuthorize([check that this is indeed an invited user])
#Secured(['ROLE_USER', 'RUN_AS_INVITED_USER'])
and it all works. The trick was to make the ROLE_RUN_AS_INVITED_USER able to change acl's.
Reference:
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/runas.html
http://grails-plugins.github.io/grails-spring-security-acl/docs/manual/guide/2.%20Usage.html#2.5%20Run-As%20Authentication%20Replacement

Spring Security User Roles Per Organization

In my application I have a top level entity called Organization. The relationship between User and Organization is many-to-many.
Because of this I could have the following scenario:
UserA has role ROLE_ADMIN for OrganizationA
UserA has role ROLE_USER for OrganizationB
I need to ensure that when UserA accesses resources for OrganizationB he is not doing it as an ADMIN. So I need an additional check that the user has the correct roles at the organization level. Is there anything built into Spring Security that allows for this? If not, does anyone know what the best way would be to about solving this?
UPDATE: A bit more information...
A User logs in and chooses which org they want to work with. That is stored in the session. Beyond that, URLs are locked down with the Secured annotation. What that means is that if UserA were to log in and select OrgA, they should be able to access /admin/user/create however, if they log in and choose OrgB they should not have access to that URL.
The long way is to add additional checks in every method where this matters. So call some service method that says "ok, you're an admin for OrgA but not for OrgB and you're logged in using OrgB, so deny this request".
I'm hoping for a more grails / spring-security way of handling this.
You can probably do this by using a custom AccessDecisionVoter. The vote method will supply you with the "configuration attributes" for the resource (method or URL), which will typically be the required roles, and you can obtain the current user's roles/authorities either directly from the Authentication object, or by reading the current org and selecting the appropriate roles for the user.
I'm assuming that you have some way of differentiating the user's roles, based on the org they've selected.
Essentially, you'd be writing an extended version of the standard RoleVoter, which takes the organization into account.
I think I'm little late here but this is what worked for me:
When an organization is selected, you can set a new Authentication object with new roles in your session(The previous Authentication object gets invalidated). Something like this:
#RequestMapping(value = "/org-a")
String orgA(HttpServletRequest request) {
request.getSession().setAttribute("org", "org-a")
Organization org = new Organization("org-a")
reloadRolesForAuthenticatedUser(org)
....
}
private void reloadRolesForAuthenticatedUser(Organization org) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication()
List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), org)
List<GrantedAuthority> authorities = getAuthorities(newRoles)
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(),auth.getCredentials(),authorities)
SecurityContextHolder.getContext().setAuthentication(newAuth)
}
private List<GrantedAuthority> getAuthorities(List<String> roles) {
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>()
if (!roles.isEmpty()) {
for (String r : roles) {
auths.add(new SimpleGrantedAuthority(r))
}
}
return auths
}

asp.net mvc user authentication/permission

i'm new to asp.net mvc and starting the following project. The company wants an intra-net website for various groups of people to upload files to a database, run reports off the it and amend data in several master tables in the database. The company use Active Directory and do not want the users to log in again to use the web site. The website will have different sections for various groups and the user's access to a particular page should be controlled from a database.
So far this is what i've come up with
changed the membership provider to link to the active directory server (based on Mike's blog post)
removed AccountController and the Views/Account folder
created a custom authentication class based on this link
I need to pull from a table in the database, based on user's AD id, his "role" (int), then cast it into the relevant SiteRoles. Would implementing this query in CustomAuthorizeAttribute be adviseable? is there a better place to pull the data from the table and store it somewhere so it can be reused rather than having to run a database query every time AuthorizeCore is called (which will happen whenever a user invokes a controller/action)?
A custom AuthorizeAttribute is definately the way to go as it will be applied before all other action filters.
Kindness,
Dan
I would use the out-of-the box ActiveDirectoryMembershipProvider rather than a custom attribute (because reinventing the wheel is generally bad, and reinventing the wheel in the area of security is bad to the point of incompetence in most cases), and the AzMan Role Provider to map AD groups and accounts to app roles.
This pairing gives you far more features out of the box (e.g., standardized GUI interface for permissions) than custom code, and is probably more secure, too.
You could do everything you want using the MVC provided FormAuthentication. Just create your custom ValidateLogOn method in the AccountController. Example:
public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
{
if (!ValidateLogOn(userName, password))
{
return View();
}
FormsAuth.SignIn(userName, rememberMe);
Session["userlogin"] = userName;
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Where your ValidateLogOn will be something like:
private bool ValidateLogOn(string userName, string password)
{
if (String.IsNullOrEmpty(userName))
{
ModelState.AddModelError("username", "You must specify a username.");
}
if (String.IsNullOrEmpty(password))
{
ModelState.AddModelError("password", "You must specify a password.");
}
/*
* Do your LDAP Validation stuff (DB queries, etc) here.
*/
}

Resources