When a users login token has expired (ie. they have been logged out) on a page that has AJAX enabled content, if they select a AJAX link on the page it will appear to complete succesfully. However this is not the case. The content that was returned to the page is the Login Redirection. Is there any way to have the AJAX call redirect to the login page if the user is logged out? From what I can see the obvious way would be to add code to the Controller which would pass an error to the AJAX caller so it would handle the users state however because this is forms authentication the authentication happens prior to the controller being called.
Any thoughts on how to handle this? Thanks in advance!
you can customize [Authorize] attribute like this
public class CustomAuthorize : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//you can change to any controller or html page.
//filterContext.Result = new RedirectResult("/Account/Login");
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
string destinationUrl = UrlHelper.GenerateContentUrl(FormsAuthentication.LoginUrl, filterContext.HttpContext);
filterContext.Result = new JavaScriptResult()
{
Script = "window.location = '" + destinationUrl + "';"
};
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
you can use this attribute same like you use [Authorize] attribute on controller or perticular action.
[CustomAuthorize]
public class UserController : Controller
{
// your actions here
}
or
public class UserController : Controller
{
[CustomAuthorize]
Public ActionResult Indes()
{
// your code here
}
}
Related
I am using default Web Application template for MVC4 in Visual Studio. How can I write Authorize Attribute to redirect user after succesfull login? This attribute should look like this: [UserRedirect("username")] whether anyone use "username" login redirect should be made. Where do I apply this attribute? To the login page or index? Thanks for answer.
You need to override OnAuthorization method of AuthorizeAtribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class UserRedirectAttribute: AuthorizeAttribute
{
public string UserName{ get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.onAuthorization(filterContext);
if(base.AuthorizeCore(filterContext.HttpContext) == true)
{
//here put all the a logic for redirect condition ()
if(filterContext.HttpContext.User.Identity.Name.Equals(this.UserName,StringComparer.Ordinal)
{
//if you should do the redirect
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Redirect controller name",
action = "Redirect action name"
})
);
}
}
}
}
Regarding the usage:
If it is an authorize attribute that is going to replace default authorize attribute you should on any authorized Action/Controller
EDIT:
Based on your last comment you don't have to use an attribute at all. Just add the redirect logic at the end of your login action:
[HttpPost]
public ActionResult Login(LoginModel model)
{
bool userAuthenticationResult = // here goes your authentication logic
if(userAuthenticationResult && HttpContext.User.Identity.Name.Equals(this.UserName,StringComparer.Ordinal))
{
//setup cookie/token any other things you need for the authentication to work
return RedirectToAction("ActionName","ControllerName");
}
}
I want to enable CORS for an action in my asp.net mvc 4 web site.
This is possible for web api
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
Is there a similar solution for mvc web site?
I also want to be able to restrict this for origin web sites I want.
Thanks
i think you need to create your Custom authorization Like this:
/// <summary>
/// Referrer Url Custom Authorize
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ReferrerUrlAuthorize : AuthorizeAttribute
{
protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
IList<string> webSitesAllowed = new List<string>() { "http://mywebsite.com", "http://customersite.com" };
string urlReferrer = System.Web.HttpContext.Current.Request.UrlReferrer.AbsoluteUri;
//checking if the referrer url exists in your list of sites allowed
if (!webSitesAllowed.Contains(urlReferrer))
return false; //access denied
return true;
}
}
and in your controller class must be set the ReferrerUrlAuthorize
[ReferrerUrlAuthorize]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
return View();
}
}
I have an ASP.NET MVC based application that allows different levels of access depending on the user. The way it currently works is when a user accesses a page, a check is done against the database to determine the rights that user has. The view is then selected based on the level of access that user has. Some users see more data and have more functionality available to them than do others. Each page also makes a variety of ajax calls to display and update the data displayed on the page.
My question is what is the best way to ensure that a particular ajax call originated from the view and was not crafted manually to return or update data the user does not have access to? I would prefer not to have to go to the database to re-check every time an ajax call is made since that was already done when the user initially loaded the page.
Check out the Authorize Attribute, you can put it on an entire controller or just specific methods within your controller.
Examples:
[Authorize(Roles = "Administrator")]
public class AdminController : Controller
{
//your code here
}
or
public class AdminController : Controller
{
//Available to everyone
public ActionResult Index()
{
return View();
}
//Just available to users in the Administrator role.
[Authorize(Roles = "Administrator")]
public ActionResult AdminOnlyIndex()
{
return View();
}
}
Alternately, you can write a custom Authorize attribute to provide your own logic.
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
IPrincipal user = httpContext.User;
var validRoles = Roles.Split(',');//Roles will be a parameter when you use the Attribute
List<String> userRoles = GetRolesFromDb(user);//This will be a call to your database to get the roles the user is in.
return validRoles.Intersect(userRoles).Any();
}
}
To use:
[CustomAuthorizeAttribute(Roles = "Admin,Superuser")]
public class AdminController : Controller {
}
If iyou are using a post use
[Authorize]
[ValidateAntiForgeryToken]
If iyou are using a get use
[Authorize]
You can also use this custom attribute
public class HttpAjaxRequestAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
if (!controllerContext.HttpContext.Request.IsAjaxRequest())
{
throw new Exception("This action " + methodInfo.Name + " can only be called via an Ajax request");
}
return true;
}
}
Then decorate your action as below
[Authorize]
[HttpAjaxRequest]
public ActionResult FillCity(int State)
{
//code here
}
Remember to "Mark/Tick" if this solve your problem.
It depends on what type of session mechanisam you are using . Are you using default membership provider ? If not than you can pass user's id and sessionid make sure that user session is valid and user has required permission to make that call .
Along with the Authorize attribute, you can also allow only Ajax requests using custom attributes as shown here.
Thanks
I took over an MVC 3 Razorview project from a colleague. I created a forgotten password page, however when clicking on the forgotten password link on the Log on page, the website asks the user to log in. I did some googling and implemented the solution for white listing actions using the [AllowAnonymous] attribute. However this did not resolve the issue.
Stepping through the code the forgotten password action is never called. It is pushed straight to the LogOn action on the Account Controller. The _ViewStart.cshtml has the following code which is called even though the forgotten password layout doesn't use it and has a layout set in the code.
#{
Layout = Request.IsAuthenticated ? "~/Views/Shared/_Layout.cshtml" : null;
}
You have to include all the action methods of the controller, that are used in the view, in the white list(using [AllowAnonymous]). I had the same issue with a RecoverPassword page and I realized that my layout invoked a menu method that wasn't in the white list.
You can try this. http://blog.tomasjansson.com/2011/08/securing-your-asp-net-mvc-3-application/
UPDATE
The following code works fine. It implements the OnAuthorization in the base class itself.
public class MyBaseController : Controller
{
protected override void OnAuthorization(AuthorizationContext filterContext)
{
var skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(
typeof(AllowAnonymousAttribute), true);
if (!skipAuthorization)
{
base.OnAuthorization(filterContext);
if (!User.Identity.IsAuthenticated)//Implement your own logic here
{
var url = new UrlHelper(filterContext.RequestContext);
var logonUrl = url.Action("LogOn", "Home", new { reason = "NotAuthorized" });
filterContext.Result = new RedirectResult(logonUrl);
}
}
}
}
public class HomeController : MyBaseController
{
public ActionResult Index()
{
return View();
}
[AllowAnonymous]
public ActionResult PasswordReset()
{
return Content("reset your password");
}
[AllowAnonymous]
public ActionResult LogOn(string reason)
{
return Content("please log in");
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class AllowAnonymousAttribute : Attribute
{
}
I have a public facing MVC3 site using forms authentication. Using forms authentication, if a user isn't authorized it sends a redirect to a login page. I don't desire this behavior, and would instead like the server to respond with 401 unauthorized. Is there a simple way of accomplishing this?
Do you mean something like this?
public class 401AuthorizeAttribute : AuthorizeAttribute
{
private class Http401Result : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
// Set the response code to 401.
context.HttpContext.Response.StatusCode = 401;
context.HttpContext.Response.End();
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new Http401Result();
}
}
You'll have to use this attribute instead of [Authorize].