How to check if user is authorized inside Action - asp.net-mvc

Usually I protect my Actions with [Authorize] but this time I need to check if a user is authorized inside the action.
Eg
if(userIsAuthorized) {
//do stuff
}
else {
//return to login page
}
I believe I am using 'Forms Authentication'
This question is kind of similar to this but none of the answers given seemed to work.
EDIT: I have done some more digging- it seems if I breakpoint on an Action that has [Authorize], the User.Identity is set, but on Actions without it, the User.Identity is empty, even if I am logged in

If you just want to know if the user is logged in:
if (User.Identity.IsAuthenticated) { ... }
If you are trying to do anything role-specific:
if (User.IsInRole("Administrators")) { ... }
The User instance is a public property of the Controller class, so you always have access to it from a Controller you write. If no user is logged in you should have a GenericPrincipal for the User and a GenericIdentity for the User.Identity, so don't worry about checking for nulls.

Request.IsAuthenticated should work for what you're trying to do.

I suggest first figuring out what kind of Authorization your using. ;)
The answer you posted is correct. From what I remember poking around the [Authorize] attribute and related ActionFilter code MVC internally calls Page.User.Identity.IsAuthenticated just like those code examples.

Create an attribute like this: OnActionExecuting will get executed first before other code from the action
public class IsAuthenticatedAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//do your validations here. and redirect to somewhere if needed.
filterContext.HttpContext.Response.Redirect("/") //this will send user to home.
}
}
on each action where you need to check, add attribute like this:
[IsAuthenticatedAttribute]
public ActionResult ActionName(parameters?)
{
// no need to worry about checking here.
//do you action things
}
EDIT:
This one still completes the action and then only redirect it. Not so much useful.

Put annotation [Authorize] in every your Action.
Microsoft link.
Example:
public class AdministrationController : Controller
{
// GET: User/Create
[Authorize]
public ActionResult Create()
{
}
}

Related

OverrideAuthentication attribute not working? ASP.NET MVC 5

I have a super simple Authentication Attribute that I'm trying to implement in an ASP.NET MVC 5 application and I'm having some trouble. I want the attribute to be applied globally, except for specific actions within a controller (for example the login form and the home page).
I've tried decorating the action with the [OverrideAuthentication] attribute with no luck. It gives me a redirect loop error because the application is still running the authentication on the login form, and keeps trying to redirect back to the login form over and over.
Has anyone else seen this behaviour? Any idea what I've stuffed up here?
By way of example, I've created a super simple filter that is currently unimplemented:
public class BasicAuthenticationAttribute
: ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
throw new NotImplementedException();
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
throw new NotImplementedException();
}
}
If I decorate my controller/action like this:
[BasicAuthentication]
public class AccountController : Controller
{
[HttpGet]
[OverrideAuthentication]
public ActionResult Login()
{
return View();
}
}
I get a not implemented exception when I navigate to the Login action, even though that action shouldn't be running the authentication code at all. Have I misunderstood how overrides are supposed to work?
I think you have confused authentication with authorization (as many people do). It doesn't make sense to make a [BasicAuthenticationAttribute] and register it globally, because authentication only happens upon login, not on every request.
Authorization is what takes place after the user has logged in to check whether the user has the required privileges to do a specific action, and it makes sense to do authorization globally. Authorization in MVC is handled by the [AuthorizeAttribute] and you can inherit it if you need to customize the way the authorization check is done. You can also register it as a global filter.
The [AllowAnonymousAttribute] works in conjunction with [AuthorizeAttribute], and basically tells it to skip the authorization check. It should also be noted that the [AllowAnonymousAttribute] will have no effect unless it is used with the [AuthorizeAttribute].

Implementing an ActionResult across all Controllers

I'm new to MVC and trying to get my head around Controllers. Please could you comment on the following scenario?:
It is a business requirement of our application that users must accept a "privacy policy" screen when using the application. I do this by setting a cookie when the user clicks a link in the initial Home controller index view.
But, I need to make sure that any entry point in our application (i.e not just from the index page but anywhere in the application) checks for the existence of the cookie. It makes sense to me that the value could be checked by each controller, but I don't want to duplicate the same "If cookie exists do something" code on each controller. So is there a next level up I can write my method?
Hoping this makes sense!
Use Custom ActionFilterAttribute.
Create a class CheckCookie:
public class CheckCookie : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!CookieExists)// Check the Cookie exists
{
//Redirect if the cookie does not exists
filterContext.Result = new RedirectResult("~/Redirect/NoCookie");
return;
}
}
}
Controller:
[CheckCookie]//Check the Cookie exists
public ActionResult Index()
{
return View();
}
Write a custom base controller (that itself inherits the standard ASP.NET MVC controller) that contains your cookie verification code, then have your other controllers derive from that.
For instance, to make sure all my actions by default require a user to be authenticated, I use something similar to this as a base controller:
[Authorize]
public class CoreController : Controller
{
/* ... */
}
Then my home controller looks like:
public class HomeController : CoreController
{
/* ... */
}

Check conditions on each page request

I have multi-tenant ASP.NET MVC application which utilizes subdomains to determine the current tenant. Whether or not the domain is valid is determined via database table lookup.
Where would be the best place to have a function that checks if the domain is in the database?If the subdomain is not in the database, it should redirect to the Index action in the Error controller.
Placing the check in the Application_BeginRequest method in the Global.asax file doesn't work because a never ending redirect results.
Where would be the best place to have a function that checks if the domain is in the database?If the subdomain is not in the database, it should redirect to the Index action in the Error controller.
Placing the check in the Application_BeginRequest method in the Global.asax file doesn't work because a never ending redirect results.
That's the right place, you just need to check the request Url is not already /Error.
You might already be doing so, but I'd like to add that it seems pretty static information that you should cache instead of hitting the database for each request.
u can subclass actionFilter attribute and override onactionExecuting method. in this method u can make any database checks and redirect the user appropriately
public class CustomActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if(DatabaseLookup)
{
return;
}
filterContext.Result = new RedirectResult("http://servername/Error");
}
}
now u can decorate ur action methods with this custom actionfilter attribute
[CustomActionFilter]
public ActionResult mymethod()
{
//action method goes here
}

Display action-specific authorisation message for [Authorize] attribute

Is there a way to display an action-specific authorisation message for when an [Authorize] or [Authorize(Roles="Administrator")] attribute redirects the user to the sign-in page?
Ideally,
[Authorize(Roles="Administrator", Message="I'm sorry Dave. I'm afraid I can't let you do that.")]
public ActionResult SomeAdminFunction()
{
// do admin stuff
return View();
}
As I understand it, attributes are not meant to add functionality, but this seems purely informational. One could do this inside the action, but it seems inelegant compared to the use of an attribute.
Alternatively,
if (!Request.IsAuthenticated)
{
if (!User.IsInRole("Administrator"))
SetMessage("You need to be an administrator to destroy worlds."); // write message to session stack
return RedirectToAction("SignIn", "Account");
}
Is there an existing way to do this or do I need to override the [Authorize] attribute?
I would override the attribute to add my specific message.

Asp MVC [Authorize] to return a Post instead of a Get

I would like to use [Authorize(Roles="Admin")] tags on my controller methods.
If a user is not an admin I would like to return this user to my login screen.
The default behaviour of returning the user to my login page is reroute my user to "Account/Login" using a Get url.
The problem is, my website's subpages are all partial views refreshed by Ajax calls, including my login screen.
So my question is:
Is it possible to alter the class below to return a post redirect instead of a get redirect?
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
override public void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
// Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode.
if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new RedirectResult("../Account/Login");
}
}
}
Apparently the problem seemes solved by removing the
[Acceptverbs(HttpVerbs.Post)]
attribute on my Account controller's Login method.
This way we don't even have to override the AuthorizeAttribute
:)
I found a solution in Microsoft.WebPages.PreApplicationStartCode.SetupFormsAuthentication()
One need only add an appSetting named "loginUrl" to specify the login action:
<add key="loginUrl" value="~/Account/LogOn"/>

Resources