User can successfully log in but log in page shows up instead of redirecting - asp.net-mvc-4

I have a moved a project from asp.net mvc 2 to asp.net 4 and after a bit of fixing everything seemed to work.
EXCEPT for the parts of the app where you have to authorize. Without authorizing it is possible to view non-authorize pages but as soon as you try to log-in everything goes
bananas. When you log-in you get logged in (you see your name in the log-in partial) but not redirected and prompted to log-in again and you can not reach parts of the
app that is for non-authorized users. Everything works on localhost but not at deployed site.
At first i thought there was a problem with my machinekey and app-pool recykling, so i added one. Still same problem.
I know that MVC uses websecurity instead of membership but i've read that an Membership solution can exist in a mvc 4 project, and i would be glad to use my custom membershipprovider and roleprovider and save some time if it is possible.
Controller:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, true);
FormsAuthentication.SetAuthCookie(model.UserName, true);
var role = userRepo.usersInRoles.First(x => x.userMail == model.UserName);
if (role.roleName == "Business")
return RedirectToAction("Start", "Business");
if (role.roleName == "Admin")
return RedirectToAction("Index", "Admin");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return View(model);
}
Config settings for Membership & Role
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<membership defaultProvider="AccountMembershipProvider">
<providers>
<clear />
<add name="AccountMembershipProvider" type="MyApp.UI.Infrastructure.AccountMembershipProvider" applicationName="/" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="RoleMembershipProvider">
<providers>
<clear />
<add name="RoleMembershipProvider" type="MyApp.UI.Infrastructure.RoleMembershipProvider" />

Related

Is Active Directory authentication used?

I've inherited MVC4 application. It looks like Windows Authentication is used, but I also was told that "Active Directory Authentication" is used for some permissions. I do not see anything in web.config about Active Directory.
In web.config:
<authentication mode="Windows" />
<roleManager defaultProvider="DefaultRoleProvider">
<providers>
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf1234ad634e53" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</roleManager>
In Controller:
[Authorize(Roles = #"ABCD\EFG"), HandleError(ExceptionType = typeof(UnauthorizedAccessException), View = "UnauthorizedUser", Order = 1)]
public class HomeController : Controller
{ .............
}
public ActionResult MyAction()
{
if (!User.IsInRole(#"ABCD\EFG"))
{
// some code
}
//.............
}
Is "Active Directory Authentication" used in this application ?
Thank you
The windows authentication will indeed integrate with Active Directory as long as the application server is on the domain your users are registered in.
The below line in your config file enables such functionality.
<authentication mode="Windows" />
This post might help you get further:
Configure ASP.NET MVC for authentication against AD

Using OAuthWebSecurity for external login and SqlMembershipProvider for internal login

In my MVC4 project I have defined connection string to database and have defined it as SqlMembershipProvider, it works fine for local account (Login and register). but in external (facebook) login and in ExternalLoginCallback method I got this error :
"To call this method, the "Membership.Provider" property must be an instance of "ExtendedMembershipProvider"."
Here is membership node in web.config:
<membership defaultProvider="SqlProvider">
<providers>
<clear/>
<add name="SqlProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="DefaultConnection" />
</providers>
</membership>
I got the error here in ExternalLoginCallback method:
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return RedirectToLocal(returnUrl);
}
while the result containing all the required information I wanted.
I found some answers on the net such as using WebMatrix.WebData and simpleMembershipProvider, but I do not want to use simpleMembershipProvider.
Any help will be appreciated :)

WebSecurity.InitializeDatabaseConnection fails with "The Role Manager feature has not been enabled." when called from console program

I have a MVC4 application using SimpleMembership to authenticate users.
I want to add users from a console program.
The console program that references a class library that has the method that will do the user creation.
It looks like this:
public class UserBuilder
{
private static readonly SimpleMembershipInitializer _membershipInitializer;
private static readonly bool _isInitialized;
private static readonly object _initializerLock = new object();
static UserBuilder()
{
LazyInitializer.EnsureInitialized(ref _membershipInitializer, ref _isInitialized, ref _initializerLock);
}
public void HandleEvent(UserAdded #event)
{
if (!WebSecurity.UserExists("ReportModels"))
{
WebSecurity.CreateUserAndAccount("ReportModels", "ReportModels");
};
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
}
When I start my console application I get System.Configuration.Provider.ProviderException {"The Role Manager feature has not been enabled."} at the line starting with WebSecurity.InitializeDatabaseConnection.
What do I need to do to accomplish this?
I've tried:
adding the nuget package Microsoft ASP.NET Web Pages 2 Web Data to both the console project and the class library project.
the answers listed in this post: SimpleMembershipProvider not working.
verified the connection string.
verified that the tables are in place in the database.
verified that creating users and authenticating them from the MVC4 project works.
Finally solved it thanks to information found in this blog post: http://insomniacgeek.com/to-call-this-method-the-membership-provider-property-must-be-an-instance-of-extendedmembershipprovider/ and some googling.
In essence I needed to add this to my app.config file:
<system.web>
<profile defaultProvider="SimpleProfileProvider">
<providers>
<add name="SimpleProfileProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"
connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<roleManager defaultProvider="SimpleRoleProvider" enabled="true">
<providers>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
</system.web>
Please note the enabled="true" on the roleManager element. Without that the same exception will be thrown.

Getting an error implementing Roles in MVC 4

I am trying to register a user to a role but i am getting the following error:
No user found was found that has the name "MyName"
I have created an MVC 4 Application using the default template.
I have created a custom membership provider and implemented the CreateUser method as follow
public User CreateUser(User i_userToCreate)
{
using (var _db = new Repository())
{
User _user = _db.CreateUser(i_userToCreate);
MembershipUser _membershipUser = new MembershipUser(providerName: "ATWMembershipProvider",
name: _user.UserName,
providerUserKey: null,
email: _user.Email,
passwordQuestion: "",
comment: "",
isApproved: true,
isLockedOut: false,
creationDate: DateTime.UtcNow,
lastLoginDate: DateTime.UtcNow,
lastActivityDate: DateTime.UtcNow,
lastPasswordChangedDate: DateTime.UtcNow,
lastLockoutDate: DateTime.UtcNow);
return _user;
}
This is how i configured my web.config
<appSettings>
<add key="enableSimpleMembership" value="false"/>
<add key="autoFormsAuthentication" value="false"/>
</appSettings>
<system.web>
<membership defaultProvider="ATWMembershipProvider">
<providers>
<clear/>
<add name="ATWMembershipProvider" type="AroundTheWorld.Infrastructure.ATWMembershipProvider"
enablePasswordRetrieval="false"
ConnetionStringName="Context"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
equiresUniqueEmail="false"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10" applicationName="myApplication" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">
<providers>
<remove name="AspNetSqlRoleProvider" />
<add name="AspNetSqlRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<!-- note: WebMatrix registers SimpleRoleProvider with name
'AspNetSqlRoleProvider'. I don't know why but i kept it. -->
</providers>
</roleManager>
Now the authenticate method is as follow:
var MembershipProvider = new ATWMembershipProvider();
User authentictedUser = MembershipProvider.CreateUser(_userToCreate);
FormsAuthentication.SetAuthCookie(authentictedUser.UserName, true);
System.Web.Security.Roles.AddUserToRole(authentictedUser.UserName, authentictedUser.Role.Name);
Session.Add("UserID", authentictedUser.ID);
Session.Add("UserName", authentictedUser.UserName);
I have already checked the following:
My User as all necessary information
I have registered two roles in App_start "user" , "admin"
but i still getting an error that No user found was found that has the name "MyName"
In asp web form that wasn't necessary in order to secure a folder based on a role
All i am trying to do is to secure an action inside a controller to a specific "Role"
[Authorize(Roles = "admin")]
public ActionResult GetAllLocations()
{
using (var _db = new Repository())
{
return View(_db.GetLocations());
}
}
I have fixed the problem...
The problem was because I implemented only a custom membership provider without a role provider.
I have followed this blog.
Basically I have created a class MyOwnRoleProvider which inherits from RoleProvider
and:
Implemented the method called GetRolesForUser
Implemented the method called GetUsersInRole
finally I modified my web.config to
<roleManager defaultProvider="ATWRoleProvider" enabled="true" cacheRolesInCookie="true">
<providers>
<clear />
<add name="ATWRoleProvider" type="AroundTheWorld.Infrastructure.ATWRoleProvider, AroundTheWorld" connectionStringName="Context" />
</providers>
</roleManager>
after it I was able to use the following
[Authorize(Roles="admin")]
public ActionResult GetAllLocations()
{
using (var _db = new Repository())
{
return View(_db.GetLocations());
}
}
AND
#if (User.IsInRole("user"))
I hope it will be helpful for someone...

IIS Virtual Directory/Application & Forms authentication

I've setup and deployed a simple forms authentication website with membership using .NET 4.
I've created a virtual directory (now converted to "Application") in IIS7 and setup the web.config file in the virtual directory as follows:
<configuration>
<system.web>
<authorization>
<deny users="?">
</authorization>
</system.web>
<system.webServer>
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
Great! I browse to the virtual directory: ../mydomain/books/
and I'm automatically redirected to the login page specified by web.config in my root directory and the url path is placed as follows:
../Account/Login.aspx?ReturnUrl=%2fbooks
At this point, I login succesfully, but I am not redirected anywhere, and when I manually return to the directory, ../books, I'm sent back to the login page, where I'm already logged in?
So I'm confused about what my problem is! I should be successfully authenticated, and than redirected back to the directory, or at the very least be able to view it manually after I log in right?
Since I had to solve this myself, I thought I may as well post it for others in case their search brings them here.
This is everything you'll need to use Forms Authentication, allow your formatting to be exposed to anonymous users, pass credentials between an existing .Net (.aspx) web site and an MVC web application and redirect to a given url after login.
Use whatever pieces you are looking for.
Make sure your Virtual Directory/Virtual Application path for your .Net web application (.aspx) is outside of the Views directory. Also make sure you set up your Virtual Directory/Application in IIS.
I used Entity Framework and Identity with a SQLServer database to validate my users.
Your Virtual Application/Directory .Net (.aspx) web.config file needs to contain this:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<!-- other stuff -->
<system.web>
<authentication mode="Forms">
<forms
loginUrl="login.aspx"
name=".AUTHCOOKIE"
protection="All"
path="/"
domain="your_domain.com"
enableCrossAppRedirects="true"
timeout="60">
</forms>
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<machineKey
validationKey="your validation key"
decryptionKey="your decryption key"
validation="SHA1"
decryption="AES"
/>
<!-- other stuff -->
</system.web>
<location path="/path/to/your/site.css">
<system.web>
<authorization>
<allow users="?"></allow>
</authorization>
</system.web>
</location>
<!-- other stuff -->
</configuration>
Then, in the code behind your login.aspx page you'll need something like this:
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
string username = Login1.UserName;
string pwd = Login1.Password;
/* do your authentication here
connect to user store
get user identity
validate your user
etc
*/
if (user != null)
{
FormsAuthentication.SetAuthCookie(username, Login1.RememberMeSet);
System.Web.HttpCookie MyCookie = System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), false);
MyCookie.Domain = "your_domain.com";
Response.AppendCookie(MyCookie);
Response.Redirect("~/path/to/your/index.aspx");
}
else
{
StatusText.Text = "Invalid username or password.";
LoginStatus.Visible = true;
}
}
Now, in your MVC applications web.config file add this:
<configuration>
<!-- other stuff -->
<system.web>
<authentication mode="Forms">
<forms
loginUrl="Account/Login"
name=".AUTHCOOKIE"
protection="All"
path="/"
domain="your_domain.com"
enableCrossAppRedirects="true"
timeout="30"/>
</authentication>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
<machineKey
validationKey="your validation key"
decryptionKey="your decryption key"
validation="SHA1"
decryption="AES"
/>
<!-- other stuff -->
</system.web>
<location path="/path/to/your/site.css">
<system.web>
<authorization>
<allow users="?"></allow>
</authorization>
</system.web>
</location>
<!-- other stuff -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule"/>
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule"/>
<remove name="UrlAuthorization"/>
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"/>
</modules>
</system.webServer>
<!-- other stuff -->
</configuration>
In your MVC AccountController Login method should look something like this:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
/* do your authentication here
connect to user store
get user identity
validate your user
etc
*/
if (user != null)
{
await SignInAsync(user, model.RememberMe);
FormsAuthentication.SetAuthCookie(model.Email, model.RememberMe);
System.Web.HttpCookie MyCookie = System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), false);
MyCookie.Domain = "your_domain.com";
Response.AppendCookie(MyCookie);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Finally, your MVC AccountController log off method is this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
FormsAuthentication.SignOut();
return RedirectToAction("Login", "Account");
}
You need to add code to redirect to the "ReturnUrl" URL noted in the query string from within your Login page after you login.