How to redirect user after login Web API? - asp.net-web-api

If my user encounters a controller with my attribute [CustomAuthorize], he is redirected to the login page where he gets his JWT token. But on successful login I want to redirect him to the place where he initially wanted to be(the URL he wrote before was redirected to login page). what's the best way to save the path?
That's my CustomAuthorizeAttribute:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult("~/Login");
return;
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/Login");
return;
}
}
}
In other words, how to know from which request the user came from?

I'be decided to write pass a parameter to Login Controller like this
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var values = new RouteValueDictionary(new
{
controller = "Login",
RequestedAddress = filterContext.RequestContext.RouteData.Values.Values.First()
});
filterContext.Result = new RedirectToRouteResult(values);
return;
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/Login");
return;
}
}
And then to get it like this
public class LoginController : Controller
{
public ActionResult Index(String RequestedAddress)
{
return View();
}
}

Related

Redirect to Login on session expiry in MVC

How I can redirect to Login.cshtml from session_end of Global.asax on session expiry.
Response.redirect() not working there.
Please comment on it.
try this may be you will able to check the session is in process or expire
Check this
Answer is given here
check also
Here is the Class which overrides ActionFilterAttribute.
public class SessionExpireAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext ctx = HttpContext.Current;
// check sessions here
if( HttpContext.Current.Session["username"] == null )
{
filterContext.Result = new RedirectResult("~/Login/Index");
return;
}
base.OnActionExecuting(filterContext);
}
}
Then in action just add this attribute as shown :
[SessionExpire]
public ActionResult Index()
{
return Index();
}
Or Just add attribute only one time as :
[SessionExpire]
public class LoginController : Controller
{
public ActionResult Index()
{
return Index();
}
}

HOw to redirect sessiont timeout page when do AJAX call

In MVC application, I have made most of the CRUD operations call using AJAX.
Problem is , when session gets timeout then, its unable to redirect to session time out page.
Below is the related code which works fine when there is no AJAX call.
[AttributeUsage(AttributeTargets.Class)] //| AttributeTargets.Method
public class ControllerLogAndAccessFilter : FilterAttribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
\\check if session is null then redirect to session time out page.
}
}
For login, i just check against the databsae, there is nothing for memebrship provider.
[HttpPost]
public JsonResult Login(string username, string password, bool RememberMe)
{
try
{
UserDTO accDTO = new UserDTO ()
{
UsernAme = username,
Password = DataEncryption.EncryptPassword(password)
};
UserDTO AccDTO = _iAccount.UserAuthentication(accDTO);
if (AccDTO != null)
{
Session["UserId"] = 1;
Session["userdto_Session"] = AccDTO;
// Remember me
HttpCookie myCookie = new HttpCookie("appCookie");
//chkRememberMe.Checked;
if (RememberMe)
{
myCookie.Values.Add("username", username);
myCookie.Values.Add("password", password);
myCookie.Expires = DateTime.Now.AddMinutes(20);
}
else
{
myCookie.Values.Add("username", string.Empty);
myCookie.Values.Add("password", string.Empty);
myCookie.Expires = DateTime.Now.AddMinutes(5);
}
Response.Cookies.Add(myCookie);
// Remember me
return Json(AccDTO.SID, JsonRequestBehavior.AllowGet);
}
else
{
return Json(null);
}
}
catch (Exception ex)
{
}
return null;
}
AJAX Call is made for login and all CRUD operation are using $.AJAX({...});.
Ajax requests should be handled at client side itself, Try this
Attribute:
[AttributeUsage(AttributeTargets.Class)] //| AttributeTargets.Method
public class ControllerLogAndAccessFilter : FilterAttribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
//TO HANDLE AJAX REQUESTS
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
//If session is null
filterContext.Result = new JsonResult
{
Data = new
{
// put a message which sentto the client
message = "Session Time out"
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}else{
//
}
}
}
In your javascript
$.ajax(function(){
url:"",
success: function (result) {
if(result.message == "Session Time out"){
//Session timed out handle it
//window.location.href = session timeout url
}
},
});

How to develop action filter controller or action method specific

i was trying to develop a custom action filter which will check cookie is enable or not. if cookie is not enable then redirect use to a specific error page.here is my code.
public class CheckCookieAttribute : FilterAttribute, IActionFilter
{
public string prmAction{get;set;}
public string prmController{get;set;}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if(filterContext.HttpContext.Request.Cookie["YourCookie"]==null)
{
filterContext.Result = controller.RedirectToAction(prmAction,prmController)
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//The action filter logic - after
}
}
now i am using like
[CheckCookie(prmAction="MyAction",prmController="MyController")]
due to lack of good knowledge i am not being able to develop attribute driven check for cookie enable or disable.
i want to develop a code in such a way as a result i should not pass any controller name or action name. i like to use code like
[HttpPost]
[CheckCookieAttribute]
public ActionResult Save(Person oPerson)
{
return View();
}
[CheckCookieAttribute]
public class HomeController : Controller
{
public ActionResult Index()
{return View();}
public ActionResult About()
{return View();}
}
}
where i will not provide any name of controller or action name. just guide me what i need to change in my code. thanks
It seems that what you are trying to accomplish is already built into ASP.NET MVC.
I would use the [Authorize] attribute (http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.108).aspx) where you want to check if the user has a cookie.
If you want to redirect the user to a specific controller/action when the user is not authorized, you can use the following attribute instead:
public class AuthorizeUserAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Error",
action = "Unauthorized"
})
);
}
}
See ASP.NET MVC 4 Custom Authorize Attribute with Permission Codes (without roles)
Then you would use it by using:
[HttpPost]
[AuthorizeUser]
public ActionResult Save(Person oPerson)
{
return View();
}
Or if you want exactly what you asked for you can do it this way:
public class CheckCookieAttribute : ActionFilterAttribute, IActionFilter
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.Cookies["YourCookie"] == null)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { {"controller", "MyController"}, {"action", "MyAction"}});
}
else
{
base.OnActionExecuting(filterContext);
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//The action filter logic - after
}
}

Custom Filter Attribute or call in Action Method - Earlier in Request Pipeline but Performance?

I have a HomeController with about 8 or 9 Action Methods.
About 7 of these methods require a check to see if the User has a special setting or not to see if they are allowed to access these Methods and related Views.
If they are not they are redirected back to a Common Action Method and View.
public class HomeController : Controller
{
public ActionResult Index() {
UserManager um = new UserManager();
um.Punter p = um.GetPunter(User.Identity.Name);
return View(p);
}
public ActionResult PunterList() {
UserManager um = new UserManager();
um.Punter p = um.GetPunter(User.Identity.Name);
if (p.isPunter) {
return RedirectToAction("Index", "Home");
} else {
return View(p);
}
}
}
The check in 'PunterList' is done in other Action Methods, I was thinking about creating a FilterAttribute to do this check. As per the following:
public class NoPunterAttribute : FilterAttribute, IActionFilter {
public void OnActionExecuting(ActionExecutingContext filterContext) {
UserManager um = new UserManager();
um.Punter p = um.GetPunter(User.Identity.Name);
if (p.isPunter) {
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Home" }, { "action", "Index" } });
}
}
public void OnActionExecuted(ActionExecutedContext filterContext) { }
}
then put this attribute on the Action method this type of user cannot access.
[NoPunter]
public ActionResult PunterList() {
UserManager um = new UserManager();
um.Punter p = um.GetPunter(User.Identity.Name);
return View(p);
}
this puts this code in 1 place, However the UserManager.GetPunter is called twice if the User.isPunter=false. Perhaps this is not such a good idea for Performance or Memory conservation of the MVC web application.
The benefit is does the check earlier in the Request pipeline, but perhaps a method called inside of the action method would mean .GetPunter would be called only once, but further along the Request pipeline. Not sure about this, kind of split on earlier vs Performance/Memory issues.
Any suggestions or ideas would be interesting to hear. Presumably it would depend on what is done inside UserManager.GetPunter. There is some caching inside this call but it does requery the cache.
You could write a custom authorization attribute which will inject the Punter as a parameter of your action:
public class HomeController : Controller
{
public ActionResult Index()
{
UserManager um = new UserManager();
um.Punter p = um.GetPunter(User.Identity.Name);
return View(p);
}
[NoPunterAuthorize]
public ActionResult PunterList(Punter punter)
{
return View(punter);
}
}
and the custom authorization attribute:
public class NoPunterAuthorize: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
var um = new UserManager();
var p = um.GetPunter(httpContext.User.Identity.Name);
var routeData = httpContext.Request.RequestContext.RouteData;
routeData.Values["punter"] = p;
return !p.IsPunter;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Home" },
{ "action", "Index" }
}
);
}
}

Why would a custom MVC3 action filter work on one controller action but not on another?

Here's the situation. I've got a single action filter that I'm using in two different controllers. The action filter is defined as:
public class ValidSubmissionAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = filterContext.Controller;
var session = filterContext.HttpContext.Session;
var isValid = controller.TempData["IsValid"];
if (isValid == null || !(bool)isValid)
{
SharedUtilities.LogOutUser(session, controller.ViewData.ModelState);
filterContext.Result = SharedUtilities.GetThankYouRedirect();
}
}
}
When I invoke the Attribute in one controller, like this:
[HttpPost]
public ActionResult DoSomething(string button, Model data)
{
try
{
if (ModelState.IsValid)
{
TempData["IsValid"] =
Request.Form["ValidRequest"] == Session.SessionID;
Session["VerifyDoingSomethingData"] = data;
return RedirectToAction("VerifyDoingSomething");
}
}
catch (Exception ex)
{
}
}
[ValidSubmission]
public ActionResult VerifyDoingSomething()
{
ViewData.Model = Session["VerifyDoingSomethingData"];
return View("VerifyDoingSomething");
}
it functions as expected. However, when I call it from a different controller, like this:
[HttpPost]
public ActionResult Index(string button, Model data)
{
try
{
if (ModelState.IsValid)
{
TempData["IsValid"] =
Request.Form["ValidRequest"] == Session.SessionID;
Session["ViewModel"] = data;
return RedirectToAction("VerifyCancellation");
}
}
catch (Exception ex)
{
}
}
[ValidSubmission]
public ActionResult VerifyCancellation()
{
ViewData.Model = Session["ViewModel"];
return View("VerifyCancellation");
}
the attribute doesn't run at all. My breakpoint in the OnActionExecuting method doesn't get hit.
If I had to guess, I'd say there was some difference in the controllers or in the action methods, but they appear to be functionally similar. Any insights? Why would I be seeing such different behavior?
Aaaaand, I'm a schmuck.
Turns out there's a completely different execution path that I'd forgotten about. That path didn't have the TempData information to use in the ValidSubmisionAttribute. Everything is functioning correctly now.

Resources