Authentication and Authorization in Asp.net MVC 4 web application - asp.net-mvc-4

I know how to use Authorization and Authentication attributes in asp.Net webform applications but I need to upgrade my old website to MVC 4, and I am new to this and don't know how it works here.
I tried to use it globally in web.config file but it is not helping me.
I used [Authorize] attribute on the contents which I want to hide from anonymous users and used [AllowAnonymous] attribute to allow access to anonymous users.
Also, I enable Authentication in web.config file but still I am not getting any desired result from that.
As, soon as I apply [Authorize] attribute on any of the Page it simply not allow even the authenticated users.
Any help will be appreciated.
I used following code;
in Global.asax file:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LogonAuthorize());
filters.Add(new HandleErrorAttribute());
filters.Add(new System.Web.Mvc.AuthorizeAttribute());
filters.Add(new RequireHttpsAttribute());
}
And for example I want to disallow anonymous user to access my home page, I used;
[Authorize]
public ActionResult Index()
{
return View();
}
On Login page I used
[AllowAnonymous]
[HttpPost]
public ActionResult Login()
{
return View();
}
In web.config file I used
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
But I got the same problem as I mentioned earlier. Any help with a bit explanation will be appreciated.

It looks to me like you have multiple global Authorization filters, and you're using Authorize decorated classes as well. What is LogonAuthorize()?
If you're going to use a global AuthorizeAttribute filter, then don't use Authorize on your classes, and only use AllowAnonymous on methods you want anonymous users to access.
Remove any authorization elements from web.config. Leave the Authentication element.
(just noticed, this is 6 months old... I doubt you're still looking)

Related

RedisSessionStateProvider.cs with External Login Links

I'm developing an ASP.NET MVC application (targetFramework 4.5) that provides user to login to the site using Custom Authentication as well as using their Twitter account. The following libraries have been referenced
Microsoft.Owin
Microsoft.Owin.Host.Security
Microsoft.Owin.Security
Microsoft.Owin.Security.Cookies
Microsoft.Owin.Security.MicrosoftAccount
Microsoft.Owin.Security.OAuth and
Microsoft.Owin.Security.Twitter
When I click the twitter button in my web page, it takes to the twitter site, gets my credentials and back to my site. No issues here.
i 'm now integrating RedisSessionStateProvider.cs for managing session using Redis. I have added the provider file (RedisSessionStateProvider.cs) and I have updated the web.config file as follows:
<sessionState cookieless="false" customProvider="RedisSessionStateProvider" mode="Custom" timeout="20">
<providers>
<add name="RedisSessionStateProvider" port="6379" server="localhost" type="RedisProvider.SessionProvider.CustomServiceProvider" writeexceptionstoeventlog="true" />
</providers>
</sessionState>
Redis server is running and is listening on port 6379. Now if I click the Twitter button, the site takes me to the twitter authentication page and after successfully authenticating from twitter, when the callback method
public async Task ExternalLoginCallback(string returnUrl)
is fired, the code
await AuthenticationManager.GetExternalLoginInfoAsync();
is returning null.
If I comment out the sessionstate node from the config file, everything is working fine i.e. the GetExternalLoginInfoAsync() is returning the loginInfo correctly.
I'm not able to identify the root cause of this issue. Can anyone please guide me in addressing this issue?
Thanks,
Hemant.
I have same issue. I think there is a bug in RedisSessionStateProvider implementation. For now, i have a temp resolution:
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
// TODO: RedisSessionState provider will not works if remove it.
Session["hook-init-redis"] = DateTime.Now.ToString();
ViewBag.ReturnUrl = returnUrl;
return View();
}
So, you should write shomething to Session, before external login will be called.

MVC 4 SimpleMembership works fine locally but causes 401 on live server

I have a MVC 4 application that uses Simple Membership. Locally, on the dev box (IIS Express) it works fine. If I attempt to access a controller action decorated with the [Authorize] attribute I get returned to the login page as specified in the web.config.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
The login action is decorated appropriately:
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
...
}
On the live server when I try to access a controller method decorated with the [Authorize] attribute I do indeed get directed to the /Account/Login page but I am also presented with the error:
401 - Unauthorized: Access is denied due to invalid credentials.
The IIS site Authentication configuration does have Anonymous and Forms authentication enabled. The application pool is running under the 'Network Service' identity and has 'Load User Profile' as True in order to work with an IIS Local DB used for authentication.
Any ideas why I should be getting the 401?
UPDATE 1
I can confirm my _layout page is not calling any partials from any other controller marked with the [Authorize] attribute as determined in this article.
You might need to allow access to the URL
<location path="Account/Login">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
OK, I stripped this right back and found the issue was indeed due to a partial view reference on the login page, left over from the original MVC 4 Internet Application project template.
#Html.Action("ExternalLoginsList", new { ReturnUrl = ViewBag.ReturnUrl })
This partial view did utilize a controller action that I had inadvertently decorated with the [Authorize] attribute.
[Authorize(Users = "support,admin")]
[ChildActionOnly]
public ActionResult ExternalLoginsList(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return PartialView("_ExternalLoginsListPartial", OAuthWebSecurity.RegisteredClientData);
}
Total human error in the end :(

How do I opt out of authentication when using identityServer?

I'm trying WIF and using identityServer. My question is how can one opt of requiring auth on controller or controller methods ( ASP.NET MVC 4 ). I have previously used [AllowAnonymous] attribute. Anyone have any samples of how to do this? This code still redirects to the identityServer for login.
public class HomeController : Controller
{
//
// GET: /Home/
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
}
This code still redirects to the identityServer for login.
I hope you didn't put the following in your web.config, did you:
<authorization>
<deny users="?" />
</authorization>
Most WIF tutorials show this, but if you are writing an ASP.NET MVC application you should control authorization with [Authorize] and [AllowAnonymous] attributes.

Adding forms authentication (SimpleMembership) to webapi app

I'm trying to add to a MVC4 webapi project the simple membership provider authentication mechanism found in a MVC 4 web application project, for a hybrid application serving its pages with a rich JS content, which uses AJAX calls to webapi actions to perform its tasks. I need the app users to authenticate before they can work with the apps provided in these pages, so I think I'll be fine with the forms authentication. I thus need to add it to the existing WebApi project and let my authorized-only actions return a 302 (redirect user to login page) rather than a 401.
Anyway, I'm missing something because as soon as I try to use a WebSecurity method I get the following exception:
System.InvalidOperationException was caught
Message=To call this method, the "Membership.Provider" property must be an instance of "ExtendedMembershipProvider".
Source=WebMatrix.WebData
Could anyone suggest a fix? Here are the steps I took for adding authorization:
1) Web.config: add to system.web:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
Add to appsettings (the 2nd entry is for replacing 401 with 302):
<add key="enableSimpleMembership" value="true"/>
<add key="webapi:EnableSuppressRedirect" value="false" />
Also remove profile, membership and rolemanager sections from the original template (they are not intended to be used with simple membership).
2) add NuGet packages for OpenAuth (DotNetOpenAuth Core, DotNetOpenAuth ext for ASP.NET, DotNetOpenAuth 1.0(a) consumer, DotNetOpenAuth 1.0(a), DotNetOpenAuth OpenID Core, DotNetOpenAuth OpenID Relying Party).
3) add InitializeSimpleMembership.cs to Filters (the code is pretty standard, see below).
4) copy from an MVC web app project the models in AccountModels.cs, all the views in Views/Account, and the AccountController.cs.
The InitializeSimpleMembership code is here:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
private static void SeedData()
{
// seed data: users and roles
if (!WebSecurity.UserExists("TheAdminGuyName"))
WebSecurity.CreateUserAndAccount("TheAdminGuyName", "password");
if (!Roles.RoleExists("administrator")) Roles.CreateRole("administrator");
if (!Roles.IsUserInRole("TheAdminGuyName", "administrator"))
Roles.AddUserToRole("TheAdminGuyName", "administrator");
}
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "User", "UserId", "UserName", autoCreateTables: true);
SeedData();
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
This might be relevant, as it mentions your error specifically:
http://weblogs.asp.net/jgalloway/archive/2012/08/29/simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.aspx

MVC 4 Using Authorize with Custom Code Not Working

New to MVC 4. What I do not want to do is used the built-in Account management that comes with MVC 4. However, I have created an Account folder under Views, an AccountModel, and AccountController.
What I would like to do is restrict access to Views within the Account folder. for this, in my AccountController, I use the following:
[Authorize]
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
public ActionResult bob()
{
return View();
}...
On my home page, I have a link to the bob view under the Accounts view which now reroutes me to the login page (which is correct).
Now, upon form submittal, with the right credentials (anything goes) I should be able to see bob, but instead I am redirected back to the Login because I was not authorized. The code:
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
return RedirectToLocal(returnUrl);
}...
I do not want to use the built-in connect to the DB, but rather what do I need to check the username against a string and then keep an authorization = true so that I can view bob?
In the long run, I plan on connecting to a DB and pulling info back with a SPROC, so right now, I just want the user to be authenticed based upon a string that is checked.
You continue to be Redirected until ASP.net sees a Forms Authenticated cookie.
FormsAuthentication.SetAuthCookie(theUsersNameasString, boolForSessionOrPersistentCookie);
Assuming your Web.Config is configured for Forms Authentication
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
ASP.Net will look for .ASPXAUTH cookie unless the name of this cookie was altered in WEB.CONFIG