Roles not working in ActiveDirectoryMembershipProvider - c#

I have a web-site which uses forms auth and ActiveDirectoryMembershipProvider. I have an Action in controller like this:
[Authorize(Roles = "jira-developers")]
[HttpGet]
public ActionResult MonitorForm()
{
var list = Dal.GetActualData();
return View(list);
}
I'm totally sure that my user is in group with Name="jira-developers", but auth fails. If i remove Roles parameter, the auth will work fine.
What am i doing wrong? I'll be gratefull for any help!

As nobody gave me an answer i'll answer this question myself. ActiveDirectoryMembershipProvider can only handle auth and to enable roles management i had to specify rolesManager. I implemented my own RoleProvider (because i need some specific functionality) and now my Web.Config looks like this:
<system.web>
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Account/Login" timeout="45" slidingExpiration="false" protection="All" />
</authentication>
<membership defaultProvider="ADMembershipProvider">
<providers>
<clear />
<add name="ADMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="AdRoleProvider">
<providers>
<clear/>
<add name="AdRoleProvider" type="InternalAutomation.Providers.AdRoleProvider"/>
</providers>
</roleManager>
<compilation debug="true" targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />

Do you have the role defined in your Roles table? (Depending on the version you're using the table could be named slightly different than my screen shot below)
You should have an entry with a 'RoleName' of "jira-developers".
The user hitting the action should also have an entry in the '...UsersInRoles' table.

Related

MachineKey change does not reflect in web.config

In my web application, there is an administrator ability to change the validation method/algorithm to SHA1 to HMACSHA256, HMACSHA384, etc. etc.
In the code, when I retrieve the value from the web.config using ConfigurationManager, it shows as being updated.
However, when I open up the Web.config itself, the value does not appear in the MachineKey section. Why is it now showing up?
edit: The technloogy I am using is Visual Studio C# and MVC. A portion of the web.config is below:
<system.web>
<machineKey validationKey="22FEA7D6533FCCE331C2342A1801051F5E2890749CB2D5EF2EEABF8B0D944F389F46FA061D1A203EB75F3A9197914299676917FFD355456CFA0B49CA4C30B348"
decryptionKey="30B2FA2A8C54665E18D9A35E3541BFED6A3E8A640DBA4070" />
<authentication mode="Forms">
<forms name="FormsAuth1" loginUrl="https://localhost/OidcApplication/Oidc/Authenticate" timeout="2880" requireSSL="false" />
</authentication>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<httpModules>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
This is how I retrieve the machine key values:
machineKeyConfig = (MachineKeySection)GetConfigurationSection("system.web/machineKey");
And this is how I set the machine key values:
var machineKeyConfig = (MachineKeySection)GetConfigurationSection("system.web/machineKey");
machineKeyConfig.DecryptionKey = machineKeySettings.DecryptionKey;
machineKeyConfig.Validation = machineKeySettings.Validation;
machineKeyConfig.ValidationKey = machineKeySettings.ValidationKey;
machineKeyConfig.CurrentConfiguration.Save(ConfigurationSaveMode.Minimal);
First of all, I would check whether the file you are saving to is the same you are reading:
var ConfigFilePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
By the way, what's the class and namespace of the GetConfigurationSection method?

Forms Auth: Where’s my auth cookie gone?

Where’s my auth cookie gone?
When redirecting from my SSO to a client application, the .ASPXAUTH cookie is lost but only if the two sites are not on the same server.
In Fiddler, I can see the cookie being set by the SSO to the Response, in the correct cookie path for the client app. Upon redirecting however, I see that the request does not bear the cookie.
Response after logging into SSO:
Request back to client application:
Relevant sections of the Login apps web.config:
<machineKey compatibilityMode="Framework20SP2"
decryption="AES"
decryptionKey="<a valid RSA key>"
validation="SHA1"
validationKey="<a valid HMACSHA256 hash>"
/>
<!-- "SHA1" actually implements HMACSHA256, but for one reason or another, we can't specify it explicitly. -->
<authentication mode="Forms">
<forms loginUrl="Index"
cookieless="UseCookies"
requireSSL="false"
name=".ASPXAUTH"
path="/path/to/SSO-Virtual-Directory/"
slidingExpiration="true"
timeout="20"
enableCrossAppRedirects="true"
protection="All"
ticketCompatibilityMode="Framework20"
/>
<!-- set cookie path relative to virtual path of the application in IIS. See Application -> Advanced Settings to see the virtual path.
Cookie Paths, Domains, and Names are all CASE SENSITIVE!!!!!
Be sure to check the virtual path, as it doesn't update when you rename path tokens to change case. you will have to recreate the application to update the virtualpath-->
</authentication>
<!--SSOConfig Providers-->
<membership defaultProvider="SqlMembershipProvider" >
<providers>
<clear />
<add name="ADMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName"
enableSearchMethods="false"
connectionUsername="<a valid domain username"
connectionPassword="<a valid password>"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
/>
<!-- do not set applicationName= .-->
<add name="SqlMembershipProvider"
connectionStringName="SqlConnectionString"
applicationName="SSO"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
minRequiredNonalphanumericCharacters="0"
type="System.Web.Security.SqlMembershipProvider"
/>
<!-- for some messed up reason applicationName is required.-->
</providers>
</membership>
<roleManager defaultProvider="SqlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/path/to/Virtual-Directory/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All"
>
<!--set cookie path relative to virtual path of the application in IIS. See Application -> Advanced Settings to see the virtual path. eg: /secure/sso/CentralLogin/ on Exodus.
Cookie Paths, Domains, and Names are all CASE SENSITIVE!!!!!
Be sure to check the virtual path, as it doesn't update when you rename path tokens to change case. you will have to recreate the application to update the virtualpath-->
<providers>
<clear />
<add name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlConnectionString"
applicationName="SSO"
/>
<!-- set ApplicationName-->
</providers>
</roleManager>
Client Web.config:
<machineKey compatibilityMode="Framework20SP2"
decryptionKey="<The same RSA key>"
validation="SHA1"
validationKey="<The same HMACSHA256 hash>"
/>
<authentication mode="Forms" >
<forms loginUrl="~/login/Index"
name=".ASPXAUTH"
path="/Payment/"
requireSSL="false"
slidingExpiration="true"
timeout="20"
cookieless="UseCookies"
enableCrossAppRedirects="true"
protection="All"
ticketCompatibilityMode="Framework20"
/>
</authentication>
<membership defaultProvider="SqlMembershipProvider" >
<providers>
<clear />
<add name="ADMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName"
enableSearchMethods="true"
connectionUsername="<a valid domain username"
connectionPassword="<a valid password>"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
/>
<add name="SqlMembershipProvider"
connectionStringName="SqlSSOConnection"
applicationName="SSO"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
minRequiredNonalphanumericCharacters="0"
type="System.Web.Security.SqlMembershipProvider"
/>
</providers>
</membership>
<roleManager defaultProvider="SqlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/Payment/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All"
>
<providers>
<clear />
<add name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlSSOConnection"
applicationName="SSO"
/>
</providers>
</roleManager>
Both sites are MVC5 on .Net 4.5.2.
Does anyone have any ideas as to whats going wrong, and what I can do about it?
So as we seems to found out in comments, the problem is SSO and client reside on different domains\ips and so cookie set for SSO will not be passed to client by browser. There are different ways to solve this, but they require change of how your general SSO process works.
As I understand you only have problem with that in development environment, not on production. If so, suppose your SSO is on 10.0.0.1 and your client is on 127.0.0.1. Then map client.yoursite.local domain (in your corporate DNS or just in /etc/hosts file) to 127.0.0.1 and yoursite.local to 10.0.0.1, and use domain names instead of raw ip addresses. Then in SSO set cookie with domain of ".yoursite.local". This then should be delivered correctly to your client application, and will not require significant changes to how your SSO process works.

SessionManager and Session is null randomly

I have been faced with this problem for months and I have read almost all I can about this and implemented most solutions but still nothing has changed. I don't know where I am making my mistake.
I am using a custom SessionManager class to get/set values into Session easily in my ASP.net CMS websites' admin panels. When the user logins I store user data to the Session then read in Admin.master page to check if the user is logged in. On different servers and also on localhost, the SessionManager.CurrentUser value is null at random times, sometimes 2 minutes sometimes 20 minutes after login, whether the page is idle or not. All my websites have the same problem.
My SessionManager.cs is
public class SessionManager
{
public SessionManager() { }
public static User CurrentUser
{
get { return (User)HttpContext.Current.Session["crntUsr"]; }
set { HttpContext.Current.Session["crntUsr"] = value; }
}
public static string CurrentAdminLanguage
{
get
{
if (HttpContext.Current.Session["crntLang"] == null) HttpContext.Current.Session["crntLang"] = SiteSettings.DefaultLanguage;
return HttpContext.Current.Session["crntLang"].ToString();
}
set
{
HttpContext.Current.Session["crntLang"] = value;
}
}
}
Note: User class is [Serializable]
In Admin.master Page_Load
if (SessionManager.CurrentUser == null) Response.Redirect("../login");
In web.config
<system.web>
<sessionState mode="InProc" customProvider="DefaultSessionProvider" cookieless="UseCookies" regenerateExpiredSessionId="true" timeout="60"/>
<machineKey validationKey="CC0...F80" decryptionKey="8BF...1B5" validation="SHA1" decryption="AES"/>
<authentication mode="Forms">
<forms loginUrl="~/login" timeout="60" slidingExpiration="true" cookieless="UseCookies" />
</authentication>
<system.webServer>
<modules>
<remove name="Session"/>
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
</modules>
I really have no more ideas to solve this issue. Please help :(
Have you checked your application pool recycling timeout? That's a common issue for session "disappearing" prior than expected. Check in IIS
If you have problems, you could set up SQL Server for handling the session, which will persist it if the AppPool is recycled, or the server is rebooted.
For more information: http://support.microsoft.com/kb/317604
Here is a sample web.config code. I don't like the regenerateExpiredSessionId in there and also it is a good practice to have your session timeout to be less than your forms timeout. How ever my advice is to carefully examine your session manager code so you can be sure that you don't reset it somehow. I can think of two thing you could do:
1. Make a test page to check when the session is empty or not and to see if you can at all set a session variable. Try to do a button click (or a ajax request) and set a session variable to keep the session alive every 1 minute or so to see if it expires again even if you keep it alive. If you don't use the Session it will expire. 2. Do some kind of logging. Every time you set a session variable do a DB log of the variable you have set. You could use the test page in 1 to see what exactly you have set in session for the current user.
<authentication mode="Forms">
<forms name="Web-site.ASPXAUTH" loginUrl="~/admin/login.aspx" protection="All" timeout="60" path="/" requireSSL="false" slidingExpiration="true" cookieless="UseDeviceProfile" domain="" enableCrossAppRedirects="false" />
</authentication>
<sessionState timeout="60" mode="InProc" />
<membership defaultProvider="WebSiteMembershipProvider">
<providers>
<clear />
<add name="WebSiteMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="DefaultConnStr" applicationName="web-site" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" requiresQuestionAndAnswer="false" enablePasswordReset="true" enablePasswordRetrieval="false" passwordFormat="Hashed" requiresUniqueEmail="false" />
</providers>
</membership>
<roleManager defaultProvider="WebSiteRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName="Web-Site.ASPXROLES" cookieTimeout="60" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All" createPersistentCookie="false" maxCachedResults="25">
<providers>
<clear />
<add name="WebSiteRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="DefaultConnStr" applicationName="web-site" />
</providers>
</roleManager>

Add Access To More Than One Action Method And View Using SqlMembershipProvider

In my MVC Project I use System.Web.Security.SqlMembershipProvider with <authorization><deny users="?" /></authorization> I restrict all access to views and action methods except <forms loginUrl="Login/Index" name=".ASPXFORMSAUTH" />. What if I want to have access to more than one Action method with View. How to add access to more than one Action method and View ?
Web.Config:
<authentication mode="Forms">
<forms loginUrl="Login/Index"
name=".ASPXFORMSAUTH" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add
name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="MySqlConnection"
applicationName="MyApplication"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed" />
</providers>
</membership>
Maybe you should use the attribute
[Authorize]
on the controller class and then use the attribute
[AllowAnonymous]
on your action method.
But i'm not sure if it will override the behavior stated under
<authorization />

Microsoft Media Platform + Forms Authentification

Forms Authentication does not work. Auth cookies are not sent to server when SMF attempts to get access to *.ism/Manifest files on a server that requires specific user roles.
What i do:
1. Create new Silverlight Smooth Streaming template with supporting RIA WCF.
2. Configure web.config :
<connectionStrings>
<add name="ApplicationServices" connectionString="Data Source=[SERVER];Initial Catalog=[CATALOG];User ID=[USER];Pwd=[PASSWORD];" providerName="System.Data.SqlClient" />
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
<properties>
<add name="Gender" />
<add name="Birthday" />
<add name="AvatarPath" />
</properties>
</profile>
<roleManager enabled="true">
<providers>
<clear />
<add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" />
<add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" />
</providers>
</roleManager>
Add Authentification Service and correct User class (add 3 props).
On client side add this to app.xaml.cs:
public App()
{
//Default things...
InitializeWebContext();
}
private void InitializeWebContext()
{
WebContext webContext = new WebContext();
var fa = new FormsAuthentication();
var ac = new AuthenticationDomainService1();
fa.DomainContext = ac;
fa.Login(new LoginParameters("user", "password"), (y) =>
{
if (!y.HasError)
{
this.RootVisual = new MainPage();
}
}, null);
webContext.Authentication = fa;
ApplicationLifetimeObjects.Add(webContext);
Resources.Add("WebContext", WebContext.Current);
}
Access is restricted by web.config file in target directory:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<authorization>
<allow roles="Role_name" />
<deny users="*" />
</authorization>
</system.web>
</configuration>
User exists in this role.
When I use the default video that's specified in Xaml (Big Bunny) - everything is fine. But when I change mediasource to a path to s restricted zone on my server I get an access error.
On the client side, I get user credentials succesfully.
Fiddler shows next thing:
When I try access to another resctricted methods ([RequiresAuthentication]) on RIA WCF, client send Auth cookies, but when SMFPlayer try access to media source, that cookie wasn`t sent.
What have I missed?
I found some workaround:
If you transfer the stream files into a subdirectory, and restrict access to it (instead of a directory with "ism" files). Manifest will be issued to anonymous users, but the data streams is only for registered (when player try touch data stream it sucessfully attach auth cookies).

Categories

Resources