How to authorize users and AD groups for my application - c#

Using Visual Studio 2015 Community, EF 6, ASP.NET MVC 5, Oracle, and using a database-first approach.
I'm trying to setup my application so that an AD and a list of users are the only ones who can access it. The list of users will not be in this AD group. This is for an internal application. In my web.config file I have the following
<authentication mode="Windows" />
<authorization>
<deny users="?" />
</authorization>
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
<providers>
<clear />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
Above each of my controllers I have the following:
[Authorize(Roles = #"domain\AD_Group, domain\user1,domain\user2,domain\user3")]
public class HomeController : Controller
I've tried different ways of handling this with:
[Authorize(Roles = #"domain\AD_Group" Users = #"domain\user1,domain\user2,domain\user3")]
And
[Authorize(Roles = #"domain\AD_Group")]
[Authorize(Users = #"domain\user1,domain\user2,domain\user3")]
But nothing seems to work. Either everyone loses access or only the AD has access. What am I doing wrong? Should I handle this in the web.config file rather than my current method? What would that look like? Thanks.

Related

Restrict access to the Logs folder

I have an ASP.NET MVC Application, which has a Logs folder, where the log files are stored. Normally, I would access it as localhost/Logs/Log.common.txt and see the logs. However, now I want to restrict it.
Now I have Logs controller, which has an Authorize attribute set to the Admin only:
namespace MyApp.Controllers
{
[Authorize(Roles = "Admin")]
public class LogsController : BaseController
{
public ActionResult Index()
{
LogFile logFile = GetLogFileByName("log.Common.txt");
return View(logFile);
}
}
}
So now, if I try to go to localhost/Logs, then I get an unauthorized access error, however, if I go directly to localhost/Logs/Log.common.txt I still can see the file. Is there any way to disable this?
For IIS7+ add following web.config file into /Logs
<configuration>
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="" roles="Admin" />
</authorization>
</security>
</system.webServer>
</configuration>
Earlier versions have slightly different syntax.
Alternatively, move /logs into /app_data

Role Manager in Web.Config

I'm trying to develop an ASP.NET MVC application which has few views. I have the following code for controller to restrict access for users:
Controller:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (!string.IsNullOrEmpty(model.ReturnUrl))
return Redirect(model.ReturnUrl);
return RedirectToAction("Edit", "Home");
}
ModelState.AddModelError("Password", "The user name or password provided is incorrect");
}
// if we got this far, something failed, redisplay form
return View(model);
}
In Web.Config:
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Home/Login" timeout="10" />
</authentication>
<authorization>
<allow users="*" />
</authorization>
<membership defaultProvider="LabourTimeProvider">
<providers>
<clear />
<add name="LabourTimeProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="LabourTime" attributeMapUsername="sAMAccountName" />
</providers>
</membership>
<roleManager defaultProvider="CustomRoleProvider" >
<providers>
<clear />
<add name="CustomRoleProvider" type="LabourTime.CustomRoleProvider" />
</providers>
</roleManager>
</system.web>
<location path="Home/Login">
<system.web>
<authorization>
<allow roles="mydomain\mygroup" />
<deny users="*" />
</authorization>
</system.web>
</location>
<location path="Home/Edit">
<system.web>
<authorization>
<allow roles="mydomain\mygroup" />
<deny users="*" />
</authorization>
</system.web>
</location>
In location path, if I use something like,
allow users = "my-user", it is working fine. Only the user is having access.
However, I would like a group of users in the mygroup to access the page. I don't know how to achieve this. I tried this code by doing some research but it didn't work. What to do I do in order to get access for the whole group?
When I try to login using an ID from the group, it doesn't work. Any suggestion is appreciated. Thanks!
There are different ways of achieving access by groups. Since you already use attributes I would suggest using the following approach:
[Authorize(Roles="Administrators")]
public class AdminController : Controller
{
.....
}
When you wanna put logic within your code you can use a construction like this:
if (Roles.IsUserInRole(userName, "ConfirmedUser")
{
.....
}
In your example, it is clear you are talking about a domain joined users group (part of an Intranet). In general Group Policy Objects (GPO) and Security Groups (SGs) are created within in Active Directory (AD), and domain users are member of these SGs.
In other cases DB hosted on DB Server can also be linked to same SGs, and in some cases DBs are not linked to any AD SGs, but have a different login account for an added security.
Access to these SGs are managed by IT Support Specialists of a given organization.
<authorization>
<allow users="*" />
</authorization>
Having said that, upon using <allow users="*" /> within Web.config will only allow domain users whose domain accounts are member of their appropriate Security Groups (SGs), created for their organization with in Active Directory (AD). As long as the application being developed is deployed on Application server joined to same domain, the GPOs and SGs security automatically gets synchronized to users and computer accounts for that domain. Therefore, only users member of SGs are able to access the application within an Intranet.

MVC5 anonymous access failing for new pages

I'm a noob when it comes to MVC security as I usually use my own, so please bear with me.
I have an MVC5 application which I'm using pretty-much straight out of the box.
It all works fine when I run it locally but after I have deployed it to a remote webserver I have authentication issues.
The pages which come with the project as standard open fine (Home, About, etc) but when I try to open one of my own I get this error:
Login failed. The login is from an untrusted domain and cannot be used
with Windows authentication.
The error is being raised on the first line of the view that tries to reference the model.
I haven't added anything to the web.config to allow or deny authentication.
An extract from the config looks like this:
<system.web>
<authentication mode="None" />
<compilation targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthenticationModule" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="LessAssetHandler" path="*.less" verb="GET" type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" resourceType="File" preCondition="" />
</handlers>
<security>
<authorization>
<add accessType="Allow" users="?" />
</authorization>
</security>
</system.webServer>
What do I need to do to allow access to the other pages?
[Edit]
The Home controller works fine. It is the standard out-of-the-box one which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ASP.NET_MVC5_Bootstrap3_3_1_LESS.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
This was a SQL server problem, not ASP authentication as I had thought.
The server name in the connection string was the fully qualified version, e.g.:
server.domain.local
Changing this to its short version server fixed this issue!

Get Windows Logon From Within ASP.NET Page

Just like the title states. Need the windows logon and domain info from within our asp.net page.
I tried
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
but it returns the IIS App Pool not the user name
Thanks
Try HttpContext.User, accessible simply as User from the code behind. It returns both the domain and username, but should be easy enough to trim for your needs. It's worked for me in the past. You can also use this to manage roles in your application, if you need to.
EDIT
Below are the relevant portions of my web.config. I also used aspnet_regsql.exe to setup the tables needed for the role manager in my database. I could then use User.Identity.Name and User.Identity.IsInRole
<connectionStrings>
<clear/>
<add name="SqlRoleManagerConnection"
connectionString="myConnectionString">
</add>
</connectionStrings>
<system.web>
<authentication mode="Windows" />
<authorization>
<deny users="?"/>
</authorization>
<roleManager enabled="true" defaultProvider="SqlRoleManager">
<providers>
<clear/>
<add name="SqlRoleManager"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlRoleManagerConnection"
applicationName="myAppName" />
</providers>
</roleManager>
</system.web>
This is my code in VB.net
var strUser = System.Web.HttpContext.Current.User.Identity.Name
so C# must be in the lines of: (not tested)
string strUser = System.Web.HttpContext.Current.User.Identity.Name;
In the Web.Config file
<configuration>
<system.web>
<authentication mode="Windows"/>
<identity impersonate="true" />
</system.web>
</configuration>

Configuring custom authorization with ELMAH

How can I configure ELMAH to display only for certain people without default ASP.NET authorization roles manager?
I (as well as many others, I think) use my own authorization logic and build my projects from zero without using provided templates. I want to log errors but it seems that it is impossible to configure ELMAH (somehow override functionality) to make it work with some other authorization or even to make it work only for particular IP addresses.
Since I will have access to web.config I tried to change these values in order to NOT display elmah by default.
<add key="elmah.mvc.disableHandler" value="false" />
<add key="elmah.mvc.disableHandleErrorFilter" value="false" />
<add key="elmah.mvc.requiresAuthentication" value="false" />
And when I want to view errors switch them from true to false and see errors, then switch back. But it seems that when I change these values all logs are erased.
What can I do?
I think the easiest approach would be to make some minor alterations to your custom authorization so the ELMAH authorization will work.
Option 1: Set the FormsAuthentication cookie on login. This way, in the web.config the allow users="username" should work. On successful login you can set the cookie with
FormsAuthentication.SetAuthCookie(theUsername, true).
The ELMAH authorization would look something like:
<location path="elmah.axd" inheritInChildApplications="false">
<system.web>
<authorization>
<allow users="theUserName" />
<deny users="*" />
</authorization>
</system.web>
...other config settings
</location>
Option 2: If you are using putting users into roles, you can override the default role provider to use the function you made to get roles. This way is a little more involved but then lets you harness role-basing authentication in the web.config, which is really nice for securing things like static file (.pdf etc) delivery. I can add code for this if interested.
I was using the ASP.NET Identity Framework, so this answer is regarding that setup. I also used the Elmah.MVC package in NuGet. I edited the following lines in web.config. (you need to supply your own user name in the allowedUser setting)
<add key="elmah.mvc.requiresAuthentication" value="true" />
<add key="elmah.mvc.allowedRoles" value="*" />
<add key="elmah.mvc.allowedUsers" value="your_user_name" />
It appears that ELMAH does get the authentication information from the current thread principal, which the ASP.NET Identity Framework will establish on your behalf upon login.
It doesn't matter how the system gets the username or roles in this case. Whether it be from the built-in providers, a provider you implement yourself, or if during your custom authentication you populate this information yourself. All it takes is to manually set the principal during something like the Application_PostAuthenticationRequest event. This should give you the jist of it.
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
//Obtain username and roles from application datastore and use them in the next line
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("userNameHere"),
new string[] { "Admin", "CanDeleteStuff", "CanEditStuff", "OtherRole" }
);
}
This will let you use something like this in your web.config
<location path="elmah.axd" inheritInChildApplications="false">
<system.web>
<authorization>
<allow roles="Elmah"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
Not to mention being able to use User.IsInRole("CanEditStuff") in your code.

Categories