MVC Active Directory Authentication by Organizational Unit - asp.net-mvc

I want to recycle AD security in my .NET MVC web application and have virtually no local security tables, if possible.
I can easily achieve this using the Authorize tag:
[Authorize(Roles="GoldDigger")]
public ActionResult Go(int companyKey)
{
var something = GetData(companyKey);
return something;
}
However, I have users who have access to multiple companies (Acme, StoreCo, etc.), and are GoldDiggers in some but not all of those companies. Let's say I create an Active Directory OU Container for each company, so I have the following AD role structure:
NTWRK\Acme\GoldDigger
NTWRK\StoreCo\GoldDigger
NTWRK\PetCo\GoldDigger
NTWRK\Megalomart\GoldDigger
To my knowledge I can no longer use the Authorize tag because the AD role required is determined by the value of the CompanyKey parameter.
What are my best options at this point to avoid adding the following to the top of every controller method? Is it possible to force the context of the authorization to a particular (non-hard-coded) organizational unit at the beginning or earlier in the session?
if (!AuthenticateAdRoleByCompany(companyKey, "Role Name Here"))
{
Explode();
return;
}

Related

MVC User Multi-Level Hierarchy and Dynamic Role Assignment

I am new to MVC, but I have a good experience in C# Winforms, Database Designing and normalization.
I want to define a User and his roles dynamically, using MVC.
Detailed Description
There is an Organization with the Head Of Department(HOD).
There are several branch offices and each office have a Branch Head Officer Working under HOD.
Each Branch Officer has a power to Assign Different Accessibility to his employees. For Eg: A Cashier can also have an access to Generate Bills.
My Problems are:
HOD(Admin) Will Create A Branch Officer(BO).HOD Will Have Access To all the defined Actions in All the controller.
How BO Can create a User that can have access only to the "Controllers's Actions" defined by the BO , and What If the Second Level User Want to create another third level user
BO and his descendants will have access only to their Branch Office. They cannot see Any details of another Branch, but HOD can view any detail of any Branch. (I want this Authorization at Server Side to avoid Cross Site Scripts)
Please guide Me, How Can I Implement This Model of Multi Access Level And Dynamic Role Management?
I have searched a lot but Couldn't found anything that can help me. BTW This Project is Employee Management System that includes Payroll, Leave Management, Employee Service Book etc.
Thanks in advance.
Just for guidance not to be take as a 100% solution.
If you are using MVC 5 you can use ASP.NET Identity Core
There are two common authorization approaches that are based on Role and Claim.
This is role based authentication. So basically you create roles as per your requirement, then you assign those roles to users. So the user immediately gets all the access rights defined for that role.
In your database:
You will have a list of users in AspNetUsers table
List of Roles in AspNetRoles table --> Admin, Branch Manager, Manager etc
Then finally decorate your controller or action with [Authorize(Roles="Admin, etc")]
[Authorize(Roles = "Admin")]
public ActionResult TestMethod()
{
ViewBag.Message = "This View is designed for the Admin's";
return View();
}
Or Whole Controller
[Authorize(Roles = "Admin")]
public class TestController
{
}
So once those are in place you will have a create an action where the admin can assign roles to others. Branch Officer can assign roles to employees.
Useful link: http://www.dotnetcurry.com/aspnet-mvc/1102/aspnet-mvc-role-based-security
http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity

asp.net identity with domain controller

I need to achieve to authenticate users with their domain user/password, if they're are in the domain controller, but the application should be available for other users as well, who should be authenticated with their own username/password; this should be stored in the application database, and their username/password to be checked against the DB.
So far i started with new asp.net template in vs2015, choosing Individual User Accounts.
I'm able to authenticate users agains domain controller, but if that is succeeded I'm unable to store the user to HttpContext.User property.
In SignInManager i call PasswordSignIn and return Success or Failure depending on AD check.
public SignInStatus PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout) {
if(AuthenticateAD(userName, password)) {
//
// to create identity/principal and assign to HttpContext.User
//
return SignInStatus.Success;
}
else {
return SignInStatus.Failure;
}
}
public bool AuthenticateAD(string username, string password) {
using(var context = new PrincipalContext(ContextType.Domain, "domainname")) {
return context.ValidateCredentials(username, password);
}
}
thanks for any hint!
The only way this really works is if you create proxy users in your application for users in AD. Essentially, you just set up a script that populates new users/updates existing users based on the data in AD on a schedule (nightly, etc. based on your needs). Then, you're dealing with just one type of user whether they're part of the domain or external. The only change you need to make is to selectively authenticate via AD or via the standard password authentication. Either way, the same user principal is in play.
You can use ADFS and allow users to choose where to authenticate. It is quite trivial to implement using default template. Just like usual login mechanics with Sign-in via google and local account.
I think this is most correct way of doing things, because domain users may end up with Kerberos/Ntlm, if they want, and it lowers complexity of your system.
Here is a WS-Fed example: Using Claims in your Web App is Easier with the new OWIN Security Components
For other stuff you can create app with default template. This app will have external authentication stuff as example.

Best Practices for Roles vs. Claims in ASP.NET Identity

I am completely new to the use of claims in ASP.NETIdentity and want to get an idea of best practices in the use of Roles and/or Claims.
After all this reading, I still have questions like...
Q: Do we no longer use Roles?
Q: If so, why are Roles still offered?
Q: Should we only use Claims?
Q: Should we use Roles & Claims together?
My initial thought is that we "should" use them together. I see Claims as sub-categories to the Roles they support.
FOR EXAMPLE:
Role: Accounting
Claims: CanUpdateLedger, CanOnlyReadLedger, CanDeleteFromLedger
Q: Are they intended to be mutually exclusive?
Q: Or is it better to go Claims ONLY and "fully-qualify" you claims?
Q: So what are the best practices here?
EXAMPLE: Using Roles & Claims Together
Of course, you would have to write your own Attribute logic for this...
[Authorize(Roles="Accounting")]
[ClaimAuthorize(Permission="CanUpdateLedger")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here
return View();
}
EXAMPLE: Fully-Qualifying Your Claims
[ClaimAuthorize(Permission="Accounting.Ledger.CanUpdate")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here
return View();
}
A role is a symbolic category that collects together users who share the same levels of security privileges. Role-based authorization requires first identifying the user, then ascertaining the roles to which the user is assigned, and finally comparing those roles to the roles that are authorized to access a resource.
In contrast, a claim is not group based, rather it is identity based.
from Microsoft documentation:
When an identity is created it may be assigned one or more claims issued by a trusted party. A claim is a name value pair that represents what the subject is, not what the subject can do.
A security check can later determine the right to access a resource based on the value of one or more claims.
You can use both in concert, or use one type in some situations and the other in other situations. It mostly depends on the inter-operation with other systems and your management strategy. For example, it might be easier for a manager to manage a list of users assigned to a role than it is to manage who has a specific Claim assigned. Claims can be very useful in a RESTful scenario where you can assign a claim to a client, and the client can then present the claim for authorization rather than passing the Username and Password for every request.
As #Claies perfectly explained, claims could be a more descriptive and is a deep kind of role. I think about them as your role's ids. I have a gym Id, so I belong to the members role. I am also in the kickboxing lessons, so I have a kickboxing Id claim for them. My application would need the declaration of a new role to fit my membership rights. Instead, I have ids for each group class that I belong to, instead of lots of new membership types. That is why claims fit better for me.
There is a a great explanation video of Barry Dorrans, talking about the advantage of using claims over roles. He also states that roles, are still in .NET for backward compatibility. The video is very informative about the way claims, roles, policies, authorization and authentication works.
Or check a related session shared by Lafi
Having used various authentication and authorisation techniques over decades, my current MVC application uses the following methodology.
Claims are used for all authorisation. Users are assigned one role (multiple roles are possible but I do not need this) - more below.
As is common practice, A ClaimsAuthorize attribute class is used. Since most controller actions are CRUD, I have a routine in the code-first database generation that iterates all controller actions and creates claim types for each controller action attribute of Read/Edit/Create/Delete. E.g. from,
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
For use at in an MVC View, a base controller class presents view bag items
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}
base.OnActionExecuting(filterContext);
}
For website menus and other non-controller actions, I have other claims. E.g. whether a user can view a particular monetary field.
bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
So where do Roles fit in?
I have a table that links a Role to a (default) set of claims. When setting user authorisation, the default is to give the user the claims of their role. Each user can have more or less claims than the default. To make editing simple, the claims list is show by controller and actions (in a row), with other claims then listed. Buttons are used with a bit of Javascript to select a set of actions to minimise the "clicking" required to select claims. On Save, the users claims are deleted and all of the selected claims are added. The web application loads claims only once, so any changes must prompt a reload within this static data.
Managers can therefore select which claims are in each role and which claims a user has after setting them to a role and those default claims. The system has only a small number of users so managing this data is straightforward
To understand the difference between Roles and Claims you must face the limitation of roles and feel how claims come over these issues, so let me give you 2 scenarios to recognize the power of claims where role can't resolve these issues :
1- Your site has two modules (pages, service ..etc) the first module for children (under 18 years old) the other for adults (over 18 years old)
your user identity has a birthday claim
You need to create a policy on this claim so the authorization for each module will be given on this value and if the age of the user is over 18 years then he can go to the adult module and not before this age.
Role is Boolean data type you can have or not have the role, it doesn't have multi values.
2- Your site has role user and you want to prevent access of users to make some maintenance without changing the code.
In claims, you can create an UnderConstrain policy that if true the user can't view the page give property authorize for role user.
At the time of writing this answer we were at '.NET 5.0' with '.NET 6.0' just around the corner. And this is my understanding of what I've seen:
Q: Do we no longer use Roles?
Yep, you're not supposed to use Roles any longer (at least not the way you did it in the previous frameworks.
Q: If so, why are Roles still offered?
To make upgrading projects easier/faster?
Q: Should we only use Claims?
yes. But be sure to check out the video posted here in the answer by #Jonathan Ramos.
Q: Should we use Roles & Claims together?
No, but you can put a role into a claim ofcourse, but be sure to upgrade your project to use Claims only.
And you should not have to write you're own attributes, you should use policy for that, as it's the way of the newer framework. If you need you're own attributes you're "doing it wrong", just create your own Requirement(handler) that's what the whole 'new' policy is all about.
In the current framework the attribute ClaimAuthorize is not even available anymore.

Web Api Security client and user

pretty new to creating Web APIs, I am currently trying to secure my API and have a couple of questions
So basically I have a Web API and an MVC app. The API currently has a controller called Account that has two methods Register and Login. The MVC app has the same controller with actions but just calls the api methods.
Now basically they way I see it, I only ever want my MVC app to use the Web API, so ill have an api key in the MVC app webconfig that gets passed to the API each time? Also users need to authenticate so at the same time passing the user details?
Will this mean I need to setup two AuthAttributes? One for a user and one for the api details?
EDIT
To take this example a bit further and to demonstrate what I need
I have an WebUI that has a controller called CreateTeam. This passes a Team model up to the api Controller method CreateTeam, the api method requires that the user is authorized to create a team. Now this works fine but....
I also have a controller on my api called LeaguesController, which has a method AddNewTeamsToLeagues. Now I have a console app that runs every hour that calls this method on the api to add new teams to leagues. Now I dont ever want anyone to call this method on the api, I only ever want the console app to be able to use it. Whats the best way to secure this?
One solution is to use the token generated by [AntiForgeryValidation] (the Razor helper is #Html.AntiForgeryToken). You can use the following token (generated on your MVC View) to assist with validation if you'd like (it can be very helpful) or use your own:
<input name="__RequestVerificationToken" type="hidden" value="some-generated-value" />
If you're using jQuery you can override the default Ajax options (jQuery.ajaxSetup() - API documentation) to automatically add this to your request headers and validate against it (in whatever implementation you want). You can also obviously send in a username and whatever else you'd like for verification uses.
Then, you can have your Web API have a filter that validates against this information (and whatever else you'd like) using AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);.
Unfortunately, until MVC6/Web API3 the two controller types have completely different implementation so you may have to write a customer filter yourself to handle authentication. There are dedicated [Authorize] attributes for both MVC and Web API but they have have different namespaces (System.Web.Http.AuthorizeAttribute vs System.Web.Mvc.AuthorizeAttribute).
Hope this helps. For further reading, you can check out this blog post.
-- Edit to reply to your updated comment about your Console application --
You could always create a Filter that only allows local connections, specific IP addresses, certain LDAP/AD Security Groups, etc to have access to a specific controller/controller action. In your case of a Console application you would need to decide how you'd want that to be secured; once you decide to you can go from there. So, say you want to allow only specific members of an AD Security Group to access the controller, you could throw together a filter like so:
namespace YourAppName.Filters
{
public class AuthorizeADAttribute : AuthorizeAttribute
{
public string Groups { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (base.AuthorizeCore(httpContext))
{
var groups = Groups.Split(',').ToList();
var context = new PrincipalContext(ContextType.Domain, "YourDomainHere");
var userPrincipal = UserPrincipal.FindByIdentity(
context,
IdentityType.SamAccountName,
httpContext.User.Identity.Name);
foreach (var group in groups)
if (userPrincipal.IsMemberOf(context,
IdentityType.Name,
group))
return true;
}
return false;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var result = new ViewResult();
result.ViewName = "NotAuthorized";
result.MasterName = "_Layout";
filterContext.Result = result;
}
else
base.HandleUnauthorizedRequest(filterContext);
}
}
}
And then apply it to a controller or a method inside of your controller, like so:
[AuthorizeAD(Groups = "SecurityGroupToAuth, League Admins, Console App Group")]
public YourViewModelHere AddNewTeamsToLeagues()
{
// do stuff
}
So, to answer your initial question: you'll likely need two different attributes/filters for the different types (between handling the AntiforgeryToken and then the console app). Unfortunately without knowing how your application and console application are hosted (different machines, same subnet, on the same network, etc) I can't give much more information but hopefully this helps point you in the right direction for creating your own filter/attribute(s).

Routing Business Branches: Granular access control in ASP.NET MVC

How should ASP.NET MVC routes be structured to allow granular role-based access control to business branches?
Every business entity is related to a branch, either by itself or via its parent entities. Is there an elegant way to authorize actions based on user-roles for any number of branches?
1. {branch} in route?
{branch}/{controller}/{action}/{id}
Action:
[Authorize(Roles="Technician")]
public ActionResult BusinessWidgetAction(BusinessObject obj)
{
// Authorize will test if User has Technician role in branch context
// ...
}
2. Retrieve branch from business entity?
{controller}/{action}/{id}
Action:
public ActionResult BusinessWidgetAction(BusinessObject obj)
{
if (!User.HasAccessTo("WidgetAction", obj.Branch))
throw new HttpException(403, "No soup for you!"); // or redirect
// ...
}
3. Or is there a better way?
I ended up using the same codebase on separate applications and databases for each business branch. This means I have to update each individually, but allows forking of features.
I rolled my own [BranchAuthorize(Roles = "Editor, Stock Keeper")] attribute which checks the authenticated user's roles against the controller action's required roles and displays a message detailing the required roles if none are assigned.
Unified branch access control would require a separate authorization service, but would allow for central rights administration.

Resources