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>
Related
In the past, I used to create a custom MembershipProvider to communicate with a custom database or logic, like this:
if (Membership.ValidateUser(model.EmailAddress, model.Password))
{
(...) // validation logic
FormsAuthentication.RedirectFromLoginPage(model.EmailAddress, false);
}
And it authenticated my user, I mean: the username is displayed in top right corner, user can access to [Authorize] controller methods, etc.
When I try this approach in MVC 5, nothing happens and it behaves like user is not authenticated.
How could I override the authentication logic in ASP.NET MVC 5?
I would like to call a Web API, service, etc. to validate my credentials and get my user authenticated having the mentioned behaviour (the username is displayed in top right corner, user can access to [Authorize] controller methods, etc) .
To have your own AuthZ you need to map the AuthorizeAttribute to your own customer Authorization Attribute.
You can achieve that using unity like this:
<alias alias="AuthorizeAttribute" type="System.Web.Http.AuthorizeAttribute, System.Web.Http" />
<alias alias="CustomAuthorizationAttribute" type="CustomSecurity.CustomAuthorizationAttribute, CustomSecurity" />
<register type="AuthorizeAttribute" mapTo="CustomAuthorizationAttribute" />
Now when anyone tries to call the controller actions that has the [Authorize] attribute on them, your CustomAuthorizationAttribute class will get called.
You can take a look at this page for your reference:
https://msdn.microsoft.com/en-us/library/ee707357(v=vs.91).aspx
I am making an asp.net web site in C# and I have a database in slq server with a table Users(id, username, password, isAdmin). The column isAdmin is int with default value 0, so if the user is admin, isAdmin = 1 else isAdmin = 0.
I have a login form in the website and when the user logs in, it creates a Session("admin") or Session("user"), depending on the isAdmin value.
So, how can I restrict access on Session("user") to admin.aspx page and to the upload folder on the site?
I don't want to add roles management in IIS, because the admin can make other users into admins (updating the isAdmin to 1)
Thanks.
Don't keep standard user & admin in separate session variables. Rather create a class that maps to your User table and store user info in it in generic way. One property of that class would be .isAdmin (integer or even boolean). Then you could simple check something like in "admin.aspx"
UserInfo objUserInfo = (UserInfo)Session("user");
if (objUserInfo.isAdmin == 0) {
Response.Redirect("User.aspx");
}
something in this logic:
after logging in, save user role in session var first.
and then in the page_load of the restricted page, check user's role and if he is not admin, redirect him to relogin with an admin account.
protected void Page_Load(object sender, EventArgs e)
{
if(session["role"].ToString().compareTo("admin")==0)
{
//load page stuff
}
else
{
Response.Redirect(your login page);
}
}
Turn off directory browsing in IIS. Add this in your web.config to prevent users from browsing folders. This is will work in IIS 7+
<configuration>
<location path="Secured">
<system.webServer>
<directoryBrowse enabled="false" />
</system.webServer>
</location>
</configuration>
I have an ASP.NET MVC 5 application. I'm using the standard ASP.NET Identity provider for user and role management. It is important that I'm using the IdentityUser from an own repository project, but this seems ok. I can register, login, edit users, and manage their roles.
I add user to Role with these lines:
UserManager.AddToRole(userdetail.Id, r);
db.Entry(userdetail).State = EntityState.Modified;
db.SaveChanges();
This seems working in DB level.
But, I can't use Role based authentications, actually the simples
HttpContext.User.IsInRole("Administrator")
doesn't working too.
[Authorize(Roles="Administrator")]
doesn't working too.
I can check only with this method, whether user is an administrator:
UserManager.IsInRole(userID, "Administrator").
Why?
In every tutorial what I found, everything works fine. The different project repository could be the reason? Or ASP.NET Identity is broken so much?
Please advice,
There seems to be an issue. [The issue by design]
The role names are case sensitive in AuthorizeAttribute and User.IsInRole
The role names are case insensitive in UserManager.IsInRole
Moreover, check for the correct role name is used for the verification.
[The above is based on the test performed with below code. Role Name="Admin", User is added to Role "Admin".]
[Authorize(Roles="Admin")] /*True as "Admin" has A capital as entered in Role name*/
public ActionResult Secured()
{
if (User.IsInRole("admin")) /*This is False*/
{
Console.WriteLine("In");
}
if(UserManager.IsInRole(User.Identity.GetUserId(), "admin")) /*This is True!!*/
{
Console.WriteLine("In");
}
return View();
}
If we change the attribute to [Authorize(Roles="admin")], it redirects to Login page.
In that case you need to logout and login the user again.
Because the roles data is also stored in cookies,
So you must issue the cookie again to work it.
Do you have this entry in your web.config?
<roleManager enabled="true">
<providers>
<clear />
<add connectionStringName="ApplicationServices" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" applicationName="/" />
</providers>
</roleManager>
Also, if I remember correctly, there is a different namespace for the role provider assembly in different versions of .NET.
I was using IsInRoleAsync in Asp.Net core and in my case the problem was that I had ignored the role's normalized name when I created it. Therefore, after updating the normalized name for the role everything worked properly.
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.
I have enabled form authentication in my ASP.NET MVC web application. I want to allow anonymous users access only to some specific pages, including Register.cshtml for instance. I was able to allow access to my CSS-file from my root web.config by doing this.
<location path="Content/Site.css">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
Now I want to allow anonymous access to other pages, like Home and Register. Do any body know how to achieve this?
In MVC you normally use the [Authorize] attribute to manage authorization. Controllers or individual actions that are dressed with that attribute will require that the user is authorized in order to access them - all other actions will be available to anonymous users.
In other words, a black-list approach, where actions that require authorization are black-listed for anonymous users using [Authorize] - all actions (not dressed with the attribute) will be available.
Update:
With MVC4 a new attribute has been introduced, namely the [AllowAnonymous] attribute. Together with the [Authorize] attribute, you can now take a white-list approach instead. The white-list approach is accomplished by dressing the entire controller with the [Authorize] attribute, to force authorization for all actions within that controller. You can then dress specific actions, that shouldn't require authorization, with the [AllowAnonymous] attribute, and thereby white-listing only those actions. With this approach, you can be confident that you don't, by accident, forget to dress an action with the [Authorize], leaving it available to anyone, even though it shouldn't.
Your code could then be something like this:
[Authorize]
public class UserController : Controller {
[AllowAnonymous]
public ActionResult LogIn () {
// This action can be accessed by unauthorized users
}
public ActionResult UserDetails () {
// This action can NOT be accessed by unauthorized users
}
}
In the Web.config i had the below authorization
<authorization>
<deny users ="?"/>
</authorization>
this causes the
[AllowAnonymous]
not work correctly, i had to remove that authorization of my Web.config, and in all the controllers put the line
[Authorize]
before the declaration of the class, to work correctly.