Authorization has been denied for this request. Always

21,941

Solution 1

You should add the [AllowAnonymous] attribute to your Controller's LogInPost

When you added the AuthorizeAttribute to your filters, it caused your controllers to assume they required authorization by default for all actions, including the one used to login.

Solution 2

Are you doing Windows Authentication? are you getting "Access Denied" error?

At times IISEXpress and IIS does some trick and to overcome of that I have hosted the site in local iis (inetmgr), enable Authentication (windows if applicable) and now run it.

P.S. not all machines have IIS server installed by default so if inetmgr doesn't work then you have to install it from Control Panel --> Windows Features --> select all the features of IIS and ASP .NET

Hope this will help.

Solution 3

Sorry for such a late response - I found your question because, having switched from IIS-hosted web api to a self-hosted web api, I've just started experiencing the same problem.

In my case, the problem was caused by how I was initialising Thread.CurrentPrincipal. Some background:

  1. I'm using a custom AuthenticationHandler (inheriting from DelegationHandler)
  2. In this handler, I'm overriding the SendAsync method to do some custom user validation.
  3. If the validation succeeds, I construct an instance of the ClaimsPrincipal class to contain some claims about the current user.

Previously, I was assigning this ClaimsPrincipal instance to Thread.CurrentPrincipal before passing the message onward to the remaining message handlers in the pipeline. However, the solution for me was to use instead the Principal member on the HttpRequestContext instance that belongs to the HttpRequestMessage instance that is passed to SendAsync. Hence (in F#),

override this.SendAsync(request : HttpRequestMessage, cancellationToken : CancellationToken) =
  // Do some user validation here first
  // .. then setup the claims (method details omitted) 
  let principal = BuildClaimsPrincipal

  // Assign to Principal on HttpRequestContext
  let requestContext = request.GetRequestContext
  requestContext.Principal <- principal

  // Rest of method omitted...

Hope this is able to help you in some way.

Share:
21,941
user3442776
Author by

user3442776

Updated on July 09, 2022

Comments

  • user3442776
    user3442776 almost 2 years

    I've already created a MVC webApi project and now I want to use Authentication and Authorization. I think I already implemented this security but for some reason something goes bad, when I write my credentials and I try to call some webApi methods the message "Authorization has been denied for this request" is shown.

    This is the code that I implemented.

    WebApiConfig:

    public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
    
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    
            config.Filters.Add(new AuthorizeAttribute());
        }
    

    Routing Config:

    public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Routing", action = "LogIn", id = UrlParameter.Optional }
            );
        }
    

    Controller:

    public class RoutingController : Controller
    {
        //
        // GET: /Routing/
        public ActionResult Index()
        {
            return View();
        }
    
        public ActionResult Projects()
        {
            return View();
        }
    
        public ActionResult Users()
        {
            return View();
        }
    
        public ActionResult LogIn()
        {
            return View();
        }
    
        [HttpPost]
        public JsonResult LogInPost(string userName, string password)
        {
            User user = new User();
            RoleByUser rByU = new RoleByUser();
            password = UserController.EncriptPassword(password);
            string url = string.Empty;
            var checkUser = user.Get(userName);
            var userExists = (from userInList in checkUser where userInList.UserName == userName && userInList.Password == password select userInList).FirstOrDefault();
            if(userExists!= null)
            {
                var roles = (from roleByUser in userExists.listOfRole select roleByUser.RoleName.Trim()).ToArray();
                IPrincipal principal = new GenericPrincipal(
                new GenericIdentity(userExists.UserName), roles);
                SetPrincipal(principal);
                url = "Routing/Users";
            }
            return Json(url);
        }
    
        private void SetPrincipal(IPrincipal principal)
        {
            Thread.CurrentPrincipal = principal;
            if (System.Web.HttpContext.Current != null)
            {
                System.Web.HttpContext.Current.User = principal;
            }
        }
    
    }
    

    HTML:

    <link href="~/css/Style.css" rel="stylesheet" type="text/css" />
    
    <div class="container">
        <div class="card card-container">
            <img id="STK" class="profile-img-card" src="Images/Softtek.png" />
            <p id="profile-name" class="profile-name-card"></p>
            <form class="form-signin">
                <span id="reauth-email" class="reauth-email"></span>
                <input type="text" id="txtUserName" class="form-control" placeholder="Email address" required autofocus />
                <input type="password" id="txtPassword" class="form-control" placeholder="Password" required />
                <div id="remember" class="checkbox">
                    <label>
                        <input type="checkbox" value="remember-me" /> Remember me
                    </label>
                </div>
                @*<button id="btnLogIn" class="btn btn-lg btn-primary btn-block btn-signin"  >Sing In</button>*@
            </form><!-- /form -->
            <button id="btnLogIn" class="btn btn-lg btn-primary">Sing In</button>
            <a href="#" class="forgot-password">
                Forgot the password?
            </a>
        </div><!-- /card-container -->
    </div><!-- /container -->
    

    JS:

    $(document).ready(function () { $('#btnLogIn').click(logIn); });

    function logIn() {
        $.ajax({
            type: "POST",
            url: "http://localhost:21294/Routing/LogInPost",
            dataType: "json",
            data: { userName: $('#txtUserName').val(), password: $('#txtPassword').val() },
            success: function (data) {
                if(data!= "" && data!= undefined && data!= null)
                    window.location.href = data;
            },
            error: function (err, e, error) {
                toastr.error('Error')
            }
        });
    
  • user3442776
    user3442776 over 8 years
    I think the problem is where I am implementing Thread.CurrentPrincipal and Current.User, because if I add the attribute [AllowAnonymous] in my API controller the app works fine, but if I Add the attribute [Authorize(Roles = RoleEntity.Collaborator)] for example the application does not recognizes this Role. So that's why I think I should implement The CurrentPrincipal in other place or in another way, do you know where I should implent?
  • user3442776
    user3442776 over 8 years
    I'm implementing my own authentication and I getting this error "Authorization has been denied for this request". I think it's because I should implemente the current principal in other place, do you know where I should do?
  • Jonathon Chase
    Jonathon Chase over 8 years
    This is a late response, but how can you expect for an action to authorize for a role if the user has yet to authenticate?