Normally use authorization settings to interact with the roles.
<location path="Register.aspx">
<system.web>
<authorization>
<allow roles="Administrator"/>
<deny users="?"/>
</authorization>
</system.web>
</location>
But I would like to have this setup in the database in a table
tblAuthorization
-IdAuthorization (Identy(1,1))
-IdCompany=5
-IdRol=5 (Administrator”)
-Path=”Register.aspx”
Is there a setting for a class to do this? There is something like Profile, RoleProvider ..
<roleManager enabled="true" defaultProvider="MyAccessRolProvider">
<providers>
<clear />
<add name="MyAccessRolProvider" type="MyAccessRolProvider" connectionStringName="MyConnectionString" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
Right now the only I think that can to implement a validation in the Page_Load event
And if it is invalid making a Redirect but I would do a little more "Professional"
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if(!ValidateAuthorization())
{
Response.Redirect("Login.aspx");
}
}
}
Could help me with examples?
Thank you very much in advance
Your best bet is to implement a custom RoleProvider - you seem to be heading in this direction as your question includes a configuration section with a custom RoleProvider (MyAccessRolProvider).
You need to specify the fully-qualified name of your RoleProvider, e.g. MyNamespace.MyAccessRoleProvider, MyAssembly.
MSDN describes how to do this, including a sample implementation.
With the understanding that you are taking about authorization at the page level you could add a HTTP module (IHttpModule) and use your module to do the authorization checking. If the authorization failed then you could redirect as appropriate.
Something like this might work:
public class MyAuthorizationModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.AuthorizeRequest += (new EventHandler(AuthorizeRequest));
}
private void AuthorizeRequest(Object source, EventArgs e)
{
bool isAuthorized = //your code here to check page authorization
if (!isAuthorized)
{
var response = //will need to get current response
response.Redirect("Login.aspx", true);
}
}
}
Note: Don't forget you'll need to add the module to your web application.
There is no out of the box support for this as far as I know however I would suggest you implement something as follows:
Create a new class that derives from AuthorizeAttribute, add an ID property and override the "AuthorizeCore" method.
public class CustomAutorizeAttribute : AuthorizeAttribute
{
public Guid ActionId { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//Check user has access to action with ID = ActionId
//implementation omitted
}
}
You can add a new database table to hold on the Actions and their associated ID values. You can either add the record to the table manually or write some code to do this using reflection (I would advise this if you have quite a few actions and are likely to add more in the future).
Once this is done you can assign users or application roles access to these actions.
In you custom Authorize attribute you have to check whether the user has access to the given action returning true or false accordingly from the AuthorizeCore method.
I would advise grabbing a collection of all actions a user has access to when a user logs in and storing them in either the server cache or some kind of distributed cache so that you aren't hitting your database on every request.
UPDATE - Sorry just realised you're using ASP.NET Forms and not MVC. My approach is for an MVC application so its probably not relevant although I'll leave it up here in case any MVC developers happen to stumble across your question.
Related
I created an ASP.NET MVC app with the following override via a custom AuthorizeAttribute implementation:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return base.AuthorizeCore(httpContext);
}
However, within this method, httpContext.User.Identity.Name is "". I need to get a handle to the current Identity.Name so I can retrieve some data based on that value. I have the following entries in web.config:
<authentication mode="Windows" />
<authorization>
<deny users="?"/>
</authorization>
At minimum, I think that the MVC site should prompt me for credentials with the configuration above, right?
I was able to get the network user ID with the following alternate code:
Request.LogonUserIdentity.Name
Are there any implications or impacts of using this code as opposed to:
httpContext.User.Identity.Name
I have a WebAPI project in which I need to use Windows Authentication for the Users but implement a Custom Role Provider for the Authorize attributes above the routes. When I implement it however I always get {"Message":"Authorization has been denied for this request."} as the result for my call. Furthermore none of my breakpoints ever trigger except for the one in the constructor of the Custom Role Provider
Controller
[Authorize(Roles="Administrator")]
[RoutePrefix("api/Constituents")]
public class ConstituentsController : ApiController
{
[Route("Constituents")]
[HttpGet]
public IDataResponse<List<IConstituent>> GetConstituents()
{
return service.GetConstituent();
}
Custom Role Provider
public class CustomRoleProvider : RoleProvider
{
public CustomRoleProvider()
{
this.UserRepo = new UserRepository(); //Breakpoint here triggers
this.RoleRepo = new RoleRepository();
}
public override string[] GetRolesForUser(string username)
{
var roles = UserRepo.GetUser(username)?.Roles?.Select(r => r.Name).ToArray();
return roles;
}
public override bool IsUserInRole(string username, string roleName)
{
var user = UserRepo.GetUser(username);
return user.Roles.Select(r => r.Name).Contains(roleName);
}
Web Config
<authentication mode="Windows"/>
<roleManager cacheRolesInCookie="false"
defaultProvider="CustomRoleProvider"
enabled="true">
<providers>
<clear />
<add name="CustomRoleProvider"
type="Data.CustomRoleProvider, Data" />
</providers>
What piece of the puzzle am I missing? I need to get the current user making the request and then check to see if the have the appropriate role in the database.
Thanks
By default, Visual Studio sets the Windows Authentication property on your project to Disabled. In the Properties pane (not the tab), you need to flip the property to Enabled. That should let you hit the breakpoints on your RoleProvider.
When you put your application on a server, you may have to perform a similar process in IIS to Enable Windows Authentication and Disable Anonymous Authentication.
We're busy porting a legacy ASP.NET web forms application to MVC. Some modules are finished with their valid Authorize attributes correctly set up, but only 1 module is going live.
So we must prevent the user from navigating to different modules (which are there, but not "live" yet). We don't want to meddle with the existing Authorize attributes, but users are currently not allowing access to these modules.
Here are my thoughts and shortfalls:
In Global.asax subscribe to Application_AuthenticateRequest and have a list of "Live" controllers, check the Request URL and throw and redirect to "Not Authorized page" if necessary. But how then I would would have to manually take routing into account where the URL may mysite/ could route to mysite/Foo/Bar/.
Could the traditional web.config authorization be used for this scenario? (This would be easier to maintain than number 1, but the web is littered with Don't do this in MVC's)
Something like this, where Customer is the controller:
<location path="Customer">
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</location>
Alternatively take the plunge, comment out ALL the Authorize attributes from the controllers which aren't live :( hoping not to go down this route...
Any push in a better direction would be greatly appreciated.
You could use the asp.net mvc filter on this case.
public class YourCustomFilter : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
List<Filter> result = new List<Filter>();
var routeData = controllerContext.HttpContext.Request.RequestContext.RouteData;
var controller = routeData.GetRequiredString("controller");
var action = routeData.GetRequiredString("action");
if (controller != "livecontrollername" && action != "liveactionname")
{
result.Add(new Filter(new YourCustomAuthorizeAttribute(), FilterScope.Global, null));
}
return result;
}
}
public class YourCustomAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
//Do something to prevent user from accessing the controller here
}
Then register this custom filter in Global.ascx, App_Start:
protected void Application_Start()
{
FilterProviders.Providers.Add(new YourCustomFilter());
}
I have setup a custom role provider implemented using the code below except it seems it's never being used, and the default provider is being used instead. When decorating the HomeController with the [Authorize(Roles = "Administrator")] attribute the CustomRoleProvider constructor is being called (I only included the constructor in to see whether the breakpoint would be hit) but none of the methods are being called. And then I am left with a HTTP Error 401.0 - Unauthorized page.
Aside from adding the necessary bits to the web.config I haven't done anything else to get Windows authentication to work. I assume it's working though because if I don't include <allow users="*"></allow> (obviously without the inclusion of the Authorize attribute) I get a 401.2.: Unauthorized: Logon failed due to server configuration error, so I assume I'm being authenticated.
I've cleared my browser cookies as per this SO post but that had no effect.
CustomerRoleProvider
public class CustomRoleProvider : RoleProvider
{
public CustomRoleProvider()
{
}
public override bool IsUserInRole(string username, string roleName)
{
bool isUserInRole = false;
// omitted for brevity
return isUserInRole;
}
public override string[] GetRolesForUser(string username)
{
string[] roles = null;
// omitted for brevity
return roles;
}
// omitted for brevity
}
web.config
<authentication mode="Windows">
</authentication>
<authorization>
<allow users="*"></allow>
<deny users="?"/>
</authorization>
<roleManager defaultProvider="CustomRoleProvider" enabled="true">
<providers>
<clear />
<add name="CustomRoleProvider" type="ProjectName.UI.Mvc.Code.Providers.CustomRoleProvider" />
</providers>
</roleManager>
Home Controller
[Authorize(Roles = "Administrator")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
This was caused from not having IIS Express set to use Windows Authentication. To fix I selected the project in Solution Explorer, opened the Properties window set Windows Authentication = Enabled and Anonymous Authentication = Disabled. Custom role provider now works.
I am building an intranet site where users will be on the corporate domain and have different permission levels. I'm currently using <authentication mode="Windows"/> to control site access, but it seems like I should be using ASP.NET Identity.
For example, say my application is a dashboard for each department in the organization. I want to create a single AD group called DashboardUsers and put everyone that can touch the site in this group.
I also want to restrict the views in the dashboard. For example, I only want the IT group to see their view, and the Finance folks see theirs, etc.
Question -- should I be using Windows Authentication to control access to the site, and then use ASP.NET Identity for user level permissions?
I have done something similar to this using only WindowsAuthentication. You can tag your actions with the Authorize Attribute:
[Authorize(Roles = #"DashboardUsers")]
As long is this user is a member of the DashboardUsers AD group they will get access to this action. It seems like MVC magic, but it really is that simple.
Unfortunately this approach will not allow you to overload an action for different Roles as the Authorize Attribute is not part of the method's signature. In your views, you would have to show different anchor tags based on the current users role.
ie:
[Authorize(Roles = #"DashboardUsers\Manager")]
public ActionResult IndexManagers()
{
..
}
or
[Authorize(Roles = #"DashboardUsers\Finance")]
public ActionResult IndexFinance()
{
..
}
EDIT AFTER COMMENT:
Since your Identity is coming from AD, you could use logic in your controller like:
if(User.IsInRole("Finance"))
{
..
}
else if(User.IsInRole("IT"))
{
..
}
And this will check which AD Group they belong too. I know it's not very elegant, but I can't imagine mixing Windows Auth with a custom identity and managing permissions in your own db would be elegant either.
I have run into this dilemma before and wound up creating a custom role provider that i used in conjunction with windows authentication. I'm not sure you need the OWIN middleware when authenticating against AD.
public class MyAwesomeRoleProvider : RoleProvider
{
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
// i talk to my database via entityframework in here to add a user to a role.
}
// override all the methods for your own role provider
}
config file
<system.web>
<authentication mode="Windows" />
<roleManager enabled="true" defaultProvider="MyAwesomeRoleManager">
<providers>
<clear />
<add name="MyAwesomeRoleManager" type="MyAwesomeNamespace.MyAwesomeRoleProvider" connectionStringName="MyAwesomeContext" applicationName="MyAwesomeApplication" />
</providers>
</roleManager>
</system.web>