I'm having a hard time implementing (or integrating) ASP.NET SimpleMembershipProvider. I already have the database tables from a previous version of the application and I don't want to create new user tables, roles, etc... I want to use the existing tables (already mapped with entity framework) so the users in the database can log in to the future application. Here's what I did:
Web.config
<authentication mode="Forms">
<forms loginUrl="~/Auth" timeout="2880" />
</authentication>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<roleManager enabled="true" />
Global.asax
WebSecurity.InitializeDatabaseConnection("MyConnectionString", "tblCreds", "IdCred", "Login", false);
// I put false in the end because I don't want it to create new tables
Controller:
[HttpPost]
public ActionResult Index(UserCreds creds)
{
if (ModelState.IsValid)
{
UserBLL bll = new UserBLL();
BaseUser authUser = bll.Authenticate(creds.Login, creds.Password);
if (authUser != null)
{
WebSecurity.Login(creds.Login, creds.Password);
return RedirectToAction("Index", "Home");
}
}
ViewBag.ErrorMessage = "Error";
return View();
}
And I'm getting this exception:
System.Data.SqlClient.SqlException: Invalid object name 'webpages_Membership'
Thanks you for your help :)
You are seeing that exception as SimpleMembershipProvider internally uses these table names. Unfortunately they are not overridable (until last i used it).
The design goal with SMP was to provide an out of the box working model of membership with its own table schema. You can configure user table name and add more column but not everything.
See this question for more information.
Related
I installed and enabled Windows authentication in IIS and in the web.config file of my project and added the [Authorize(Users = "MYDOMAIN\MyAccount") attribute to the controller, just above the Index method so that I could begin testing to be sure no one but those specified could access an IT intranet app I was working on. This worked fine after adding the following to the Web.config:
<system.web>
<compilation debug="true" targetFramework="4.7.1" />
<httpRuntime targetFramework="4.6.1" />
<httpModules>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
<authentication mode="Windows" />
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
<providers>
<clear />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
</system.web>
If I either remove the Users = part of the attribute and change it to Roles = "DOMAIN\\Group", or if I just add that after a comma, it stops working altogether:
[Authorize(Roles = "DOMAIN\\GROUP")]
or
[Authorize(Roles = "DOMAIN\\GROUP", Users = "DOMAIN\Username")]
I'm a member of the AD group I'm specifying yet neither of these work. It only works for the Users alone and at no other time. I'll be prompted for a password otherwise.
I even got it to display the current user I'm logged into Windows as and that's still working fine if I remove the attribute. Yet if I add the attribute back (with the Roles section included) I get a prompt to login despite being logged in as the user specified in the tag.
Here's part of the controller:
public class HomeController : Controller
{
[Authorize(Users = #"MYDOMAIN\MyAccount", Roles = #"MYDOMAIN\All Information Technology")]
public ActionResult Index()
{
return View();
}
Here's my RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Why is this not working? What am I missing?
You are trying to authorize Group instead of Role. Those two things are not one and the same. Unless user will be part of the Role that is authorized to access resource you will always get unauthorized result.
If you want to authorize Group you should inherit and extend AuthorizeAttribute or develop your own authorization attribute implementing IAuthorizationFilter.
Turns out that for whatever reason, the laptop I was testing on, despite being logged into the domain as an account that was a member of the group in the annotation, was being picked up as my separate domain admin account. So when I added Domain Admins to the authorize list of roles it started working. I've got a whole new problem now, why my app picks up a different account than the one I'm logged in as, but apparently I was doing everything right. See question as a reference.
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.
I've got a ASP.NET MVC page that I'd like to secure with a login and not only authenticate against an Active Directory using Forms Authentication, but also grant access only to specific roles.
web.config
<system.web>
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Home/Login" timeout=45 protection="All" />
</authentication>
<authorization>
<allow roles="Admin" />
<deny users="*" />
</authorization>
...
Controllers
[HttpGet]
public ActionResult Index() {
return View("~/ng-app/index_template.cshtml");
}
[HttpGet, AllowAnonymous]
public ActionResult Login() {
return View("~/ng-app/login_template.cshtml");
}
[HttpPost, AllowAnonymous]
public ActionResult Login(LoginDto dto) {
... // validate dto & stuff
FormsAuthentication.SetAuthCookie(loginModel.Username, loginModel.RememberMe);
}
Now, basic protection and general authentication works perfectly. I can log in with my domain account and I don't have access to any other pages as anonymous users. However, I'm somehow unable to restrict access only to a certain role. When I add <allow roles="Admin" /> to the authorization section, it does absolutely nothing. When I additionally add <deny users="*" />, I lock myself out and even after successful login, the server always returns 302 Found without doing any redirects or serving the actual file.
You should be doing the allowed roles on the controller declaration
So above your actionresult declaration put this above
[HttpGet]
[Authorize(Roles="Admin")]
public ActionResult AuthorizedView() {
return View("~/ng-app/admin_template.cshtml");
}
This will then do a check to see if the user is in the role declared or not
To declare the roles in the webconfig you could do something like below
<authorizationConfiguration>
<controllerAuthorizationMappings>
<add controller="Home" role="GeneralAccess">
<!-- Define allowed roles for actions under the Home Controller -->
<actionAuthorizationMappings>
<add action="MyTopSecretActionForSuperCoolPeopleOnly" roles="Developer,Manager,Fonzie" />
</actionAuthorizationMappings>
</add>
</controllerAuthorizationMappings>
</authorizationConfiguration>
And here is a link to the site
http://www.ryanmwright.com/2010/04/25/dynamic-controlleraction-authorization-in-asp-net-mvc/
There is far to much for me to bring it into this thread, I will turn it in to a wiki answer when I have 5 minutes
I wanted to build a membership system at the beginning of my MVC project and I used Membership.ValidateUser method to verify credentials. However I could not understand how does this method access my database and check my email and password informations.
[HttpPost]
[ActionName("Login")]
public ActionResult Login(LoginModel loginModel)
{
if (Membership.ValidateUser(loginModel.Email, loginModel.Password))
{
FormsAuthentication.SetAuthCookie(loginModel.Email, true);
return Json(true);
}
return new JsonNetResult()
{ Data = new { Error = true, Messages = new[] { new { Message = "Wrong username or password" } } } };
}
It' used the MembershipProvider specified on your Web.config file to validate the user. By default, it uses DefaultMembershipProvider
Membership.ValidateUser method at first check membership defaultProvider in your web.config file which matches with name that you provide like below:
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add name="SqlProvider" type="System.Web.Security.SqlMembershipProvider"
connectionStringName="Context" applicationName="myapp"
enablePasswordRetrieval="false" enablePasswordReset="true"
requiresQuestionAndAnswer="false" requiresUniqueEmail="true"
passwordFormat="Hashed" minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
Above configuration will call .net framework abstraction class MembershipProvider -> ValidateUser (abstract method) which implementation lies in SqlMembershipProvider -> ValidateUser method that you have configured in your web.config file [like above].In that method it simply call two store procedures of your database , first one is aspnet_Membership_GetPasswordWithFormat which check your application name, username , last login activity date and current time and based on that makes you authenticate and secondly call to other store procedure which name is aspnet_Membership_UpdateUserInfo which is self explanatory as you realize which update aspnet_membership table with columns like islockedout, lastlockoutdate, failedpasswordattemptcount.. etc.
Hope this helps you.
Here is my problem. I am creating an MVC 4 EF site from a database that I have created myself. I have a USERS table with a UserID column, a UserName column, a Hash column, and a Salt column. I would like to use simple membership and point it to my USERS table to handle logins, password changes, registrations etc. I am using the MVC 4 Web Application Template and cannot get it to connect to my database. Here is my connection string for the InitializeSimpleMembershipAttribute class to use. I was told it needed to be different from the connection string that created my entities from the database.
<add name="DBConnectionString"
connectionString="data source=SERVERADDRESS;initial catalog=DATABASENAME;user id=USERID;password=PASSWORD;"
providerName="System.Data.SqlClient" />
The only changes I made to the template's InitializeSimpleMembershipAttribute.cs is that I replaced the following line with my table data:
WebSecurity.InitializeDatabaseConnection("DBConnectionString", "USERS", "UserID", "UserName", autoCreateTables: true);
I am not sure what I am doing wrong. I have read that all you need do is give the database connection the connection string, the table for the users, the user ID column, and the username column. Does my user account database need to be exactly like the template's? This is the first time I have done database first for an MVC site.
1.) Make sure the following lines in your web.config file.
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear />
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
2.) Add the following codes to Application_Start() event in your global.asax.cs file.
Database.SetInitializer<UsersContext>(null);
if (!WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection("DBConnectionString", "Users", "UserId", "UserName", autoCreateTables: true);
}
3.) and then Clean and Run solution...