using windows authentication with active directory groups as roles - asp.net-mvc

I've read several questions on this topic,
such as here, here, here and here;
but none have provided a working solution in my case.
What I want to do:
Implement Windows authentication for a web app that is only used by our own employees. This way they should not need to log into the app, but already be authenticated by way of having logged into windows.
Also, I need to restrict certain areas of the app, based on Active Directory Security Groups that the user may be assigned to.
So I want to be able to decorate Controllers / Actions with
[Authorize(Roles="SomeRole")]
What I've tried:
I have
<authentication mode="Windows" />
in my web.config. And I have added several permutations of a <roleManager> as found in some of the posts linked to above. Currently I have this role manager
<roleManager defaultProvider="WindowsProvider"
enabled="true"
cacheRolesInCookie="false">
<providers>
<add
name="WindowsProvider"
type="System.Web.Security.WindowsTokenRoleProvider" />
</providers>
</roleManager>
as found in this post.
As it is, if I decorate a controller with [Authorize], I can access it fine.
However:
I can see in my user settings on the network, that I am part of a AD security group called "IT". But if I decorate the same controller with [Authorize(Roles="IT")] I get the blank screen that is is served by the asp.net development server for a 401 not authorized. This is unexpected. I would think that I should be able to view the page as I am logged in to windows and am part of the group "IT".
Most everything I am finding on this topic make it sound very simple to accomplish what I'm trying to do, but I am clearly missing something here.

For dev I am using IISExpress
with development server properties of the MVC project set up so that
Anonymous Authentication is Disabled and Windows Authentication is Enabled.
The web config is deployed using our TFS build server to test and release servers for which authentication is also setup as above and works in those locations as well.
In my web.config I have.
<system.web>
....
<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>
....
</system.web>
I can use
[Authorize(Roles = #"DOMAIN\ADGroup")]
Public ActionResult Index()
{...}
or
public ActionResult Index()
{
var User = System.Web.HttpContext.Current.User;
if (User.IsInRole("DOMAIN\\ADGroup"))
{
return RedirectToAction("IRSAdmin");
}
return View();
}
After i remember to logoff and log back in so the permission i was given to the AD group were applied.

Related

MVC 4 Windows Authentication

I'm relatively new to MVC, I need to retrieve username and pass it to my company library that checks for user credential.
Web.config
<authentication mode="Windows" />
<authorization>
<allow users="*"/>
<deny users="?"/>
</authorization>
Controller
[Authorize]
public class MVCAuthen : Controller
{
public string GetCredentials()
{
var userName = HttpContext.Current.User.Identity.Name;
string credential = library.Getcredential(userName);
return credential;
}
}
My question is I keep getting blank when I try to retrieve username. Can someone tell me what I'm doing wrong or how I retrieve username?
Note: I'am trying to do this locally since I'm trying to debug it.
First you should be using a Internet Application or Intranet Application template.
Then on the web.config you should comment or remove the forms authentication and use the windows authentication. Something like this:
<--
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
-->
<authentication mode="Windows" />
And add this in the 'appSettings'
<appSettings>
<add key="autoFormsAuthentication" value="false" />
<add key="enableSimpleMembership" value="false"/>
</appSettings>
Now go to you solution explorer, right click the project and go to properties. There you must change Windows Authentication to enabled.
If you do not want to allow any anonymous access you may disable Anonymous Authentication too.
Once that is done you can add the [Authorize] on any Controller or Action.
Then you should be able to login with your windows password.
If you are able to login and view the page then you can retrieve the user name like this.
var username = HttpContext.User.Identity.Name;

AllowAnonymous Attribute not working MVC 5

Inside the Azure Portal I set App Service Authentication "On" For my Web App and I use AAD as Authentication Provider.
This has worked great up until now, I need an endpoint that will allow anonymous users, however the attribute [AllowAnonymous] does not work, I am still required to sign in.
Code:
[Authorize]
[RoutePrefix("users")]
public class UsersController : Controller
{
[Route("register/{skypeid}")]
public ActionResult Register(string skypeid)
{
///stuff...
}
catch (Exception ex)
{
return Content(ex + "");
}
ViewBag.Name = name;
return View();
}
[AllowAnonymous]
[Route("exists/{skypeid}")]
public ActionResult Exists(string skypeid)
{
return Content("Hello " + skypeid);
}
I think the code is right, so does it have something to do with the fact that I use App Service Authentication for my Web App?
EDIT:
So, I found the source of the problem, In Azure if you set "Action to take when not Authenticated" to "Sign in with Azure Active Directory", it does never allow anonymous.
However, If I change it to allow anonymous then users are not prompted to sign in when trying to access a control with the [Authorize]-Attribute, it just tells me "You do not have permission to view this directory or page."
Is this intended? It seems really weird. I want users to be redirected to Login if there is an [Authorize]-Attribute.
Screenshots for clarity:
Check your web.config if you have
<authorization>
<deny users="?" />
</authorization>
its override [AllowAnonymous]
add
<location path="YourController/AnonymousMethod">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
to allow anonymous access
I've just written about this in my book - http://aka.ms/zumobook - look in Chapter 6 for the MVC section.
The basic gist of it is that you need to do a little more to enable authentication; most specifically, you need to set up an auth pipeline (Azure Mobile Apps Server SDK will do this for you) and you need to set up a forms redirect within Web.config:
<system.web>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
<authentication mode="Forms">
<forms loginUrl="/.auth/login/aad" timeout="2880"/>
</authentication>
</system.web>
Since there are several details to adding the Mobile Apps SDK to your ASP.NET application, I'd refer to the referenced chapter for those details.

Using Active Directory Membership Provider for Site Authentication

I have an MVC site that I am in the process of converting from Forms to Federated Authentication. I am able to connect to the ADFS server and verify authentication. However the site currently uses an ActiveDirectoryMembershipProvider to verify the roles of the users as different roles permit different access.
I can not figure out how to populate the MembershipProvider so that I can user things such as this:
User.IsInRole(#"MY-ROLE")
and this:
[Authorize(Roles = "MY-ROLE")]
I have this snippet in my web.config which works for forms authentication but isn't working in my federated site:
<membership defaultProvider="ADMembershipProvider">
<providers>
<clear />
<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionProtection="Secure" attributeMapUsername="sAMAccountName" connectionStringName="ADConn" connectionUsername="LotusLDAPUser" connectionPassword="LotusLDAPUser" />
</providers>
</membership>
I have read a lot of MSDN docs and am still having trouble so please don't just answer with a link to docs. I would appreciated some sample code.
UPDATE:
I added a RoleProvider to my web.config. The role provider was being used in the forms application version successfully, so I believe the values are correct I just missed adding it to the web.config of the federated version. Here is what I have:
<roleManager enabled="true" defaultProvider="ActiveDirectoryRoleProvider" cacheRolesInCookie="true" cookieName=".ADLibraryROLES" cookiePath="/" cookieTimeout="1440" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="true" cookieProtection="All">
<providers>
<clear />
<add name="ActiveDirectoryRoleProvider" connectionStringName="ADConn" connectionUsername="LotusLDAPUser" connectionPassword="LotusLDAPUser" attributeMapUsername="sAMAccountName" type="MyNamespace.ActiveDirectoryRoleProvider" />
</providers>
</roleManager>
It is still returning false for
User.IsInRole(#"MY-ROLE")
and
[Authorize(Roles = "MY-ROLE")]
For a user I know to my in "MY-ROLE"
The problem was that I wasn't setting the Session Token Cookie. In the forms authentication version I had the code:
FormsAuthentication.SetAuthCookie(user.UserName, true);
When testing the Federated version I wasn't setting the authentication cookie, this line is needed:
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);
Where token is a SessionSecurityToken created from my Claim.

Umbraco 7 Custom Membership Provider use both Umbraco Users and external Members

how can i use in Umbraco 7 the internal Users and roles who use the BackOffice and my custom users and roles (which comes from an external SQL database.
i want log in umbraco backoffice with the umbraco users as it is and with seperate Login want use external users. i have already changed the web.config
<add name="mynewMembershipProvider" type="mynewMembershipProvider, mynew"
<add name="mynewrovider" type="mynewrsRoleProvider"/>
when i go now to my custom Login i can Login my custom user . but when i try
User.Identity.IsAuthenticated
or
User.IsInRole("xyz")
umbraco is always looking at the umbraco roles.
what did i have done wrong
best regards Michael
If I understand you correctly, you are leaving CMS and back office Users as-is, and you want to allow Member login on the public facing side of your site with a custom provider?
Did you set the default provider to your new membership provider?
<membership defaultProvider="mynewMembershipProvider">
...
</membership>
The default provider in the membership section should always point to the provider being used for public-facing Members - the backoffice interally asks for the UsersMembershipProvider every time it needs to authenticate, so changing the default will not affect it at all.
It is also possible depending on your set up (I haven't tried this) that if you did not include a <clear/> directive then the original Umbraco member provider is causing problems.
Here is a full working <membership> section using a custom BCrypt hashing provider from an Umbraco 7 install of mine:
<membership defaultProvider="BCryptMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add
name="BCryptMembershipProvider"
type="cFront.Web.Security.BCryptMembershipProvider"
connectionStringName="umbracoDbDSN"
requiresUniqueEmail="0"
/>
<add name="UsersMembershipProvider" type="umbraco.providers.UsersMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="BCryptRoleProvider">
<providers>
<clear />
<add name="BCryptRoleProvider" type="cFront.Web.Security.BCryptRoleProvider"
connectionStringName="umbracoDbDSN"
availableRoles="SuperUser,Administrator,Manager,User"
/>
</providers>
</roleManager>

Problems with IIS and Custom Membership Provider + Custom Role Provider

I have developed my own classes for Custom Membership and Role providers.
Everything works locally. Nonetheless, after deploying the solution to IIS for testing, my login action seems to work (at least, the action validates the username+password and the user appears to be authenticated) but whenever I try to access actions that are decorated with annotations like
[Authorize(Roles="Employee, Admin")]
I keep getting redirected to the login page, as if the user didn't have the necessary role (he does, though).
So locally, the application succeeds in validating users and checking the authenticated user's roles before executing actions (thus, I assume that my methods on both classes are correct) but on IIS it looks like the role provider isn't working properly. Anyone happens to know where might I be wrong or how can I get a better view on my problem?
In my Web.Config:
<system.web>
(...)
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="MyApplication.Infrastructure.CustomMembershipProvider" connectionStringName="DBEntities" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider" type="MyApplication.Infrastructure.CustomRoleProvider" connectionStringName="DBEntities" applicationName="/" />
</providers>
</roleManager>
(...)
</system.web>
Thanks in advance.
EDIT: Aditional Info.
I just modified one of my actions' anotation to simply [Authorize] and it works. So, I believe that the authentication works and the problem must be related to the Role provider.
I'm using Entity Framework for my Data Model, the con. string is as follows:
I managed to register a user and log in using the that newly created account, which would mean that the DB connection and the Custom Membership Provider(?) are working properly.
A "#foreach (String str in Roles.GetRolesForUser(User.Identity.Name)){#str} prints the roles locally and doesn't print anything when deployed.
Ok, I fixed it. Here's the explanation in case someone needs it in the future:
After narrowing out the causes (as seen in my edits), I figured out that the problem must be related to my CustomRoleProvider.
That class has methods like this one:
public override string[] GetRolesForUser(string Username)
{
List<string> roles = new List<string>();
using (DBEntities _db = new DBEntities())
{
try
{
var dbRoles = from r in _db.UserRole
where r.Users.Username == Username
select r;
foreach (var role in dbRoles)
{
roles.Add(role.Role.Name);
}
}
catch
{
}
}
return roles.ToArray();
}
So I was catching an exception and not doing anything with it. I removed the try-catch block, and got this message:
There is already an open DataReader associated with this Command which must be closed first.
A bit of stackoverflowing and I found this: There is already an open DataReader associated with this Command which must be closed first
Turns out my local connection string had MultipleActiveResultSets=true but the connection string on my publish settings didn't. I modified my publish settings and voilĂ , seems to be working now.
I don't really know the advantages/disadvantages of having that setting, but it is working and I really need to move on. Thank you all for your help anyway.
I have had the similar issue. After adding machineKey to web.config everything works all right.
<system.web>
<machineKey validationKey="2E417D4AC04F20FA6CE1CF1EFE23FBF1695BF6981B605B1B8628D2182C43D0B10E48C4A83FDCE0D1D6300095D9EE1B8746A37E2C3256554405983DCAA7622875" decryptionKey="FA6D35C22BF7E5E9E4438052B924CCC017521137C5EB017D07C7038B80C5F726" validation="SHA1" decryption="AES" />
</system.web>

Resources