Search code examples
asp.net-mvciisowinasp.net-mvc-5.2owin.security

Microsoft.Owin.Security.IAuthenticationManager doesn't redirect to login page


I'm using Microsoft.Owin.Security in my application (ASP.NET MVC v 5.2.0 on .NET 4.5). But just the security part of OWIN nothing else. When a user wants to access to a protected URL, in local, the request get redirected to the login page. But when I publish the app on server, I get this window instead of redirecting:

enter image description here

my login and log-off methods are:

public void LogIn(long userId, string username, string email, bool persistent) {
    var claims = new List<Claim>{
        new Claim(ClaimTypes.NameIdentifier, userId.ToString(CultureInfo.InvariantCulture)),
        new Claim(ClaimTypes.Name, username),
        new Claim(ClaimTypes.Email, email),
        new Claim(ClaimTypes.IsPersistent, persistent.ToString())
    };
    var id = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
    var ctx = HttpContext.Current.Request.GetOwinContext();
    var authenticationManager = ctx.Authentication;
    authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    authenticationManager.SignIn(new AuthenticationProperties {
        IsPersistent = persistent
    }, id);
}

public void LogOut() {
    var ctx = HttpContext.Current.Request.GetOwinContext();
    var authenticationManager = ctx.Authentication;
    authenticationManager.SignOut();
}

and here is my startup:

public partial class Startup {
    public void ConfigureAuth(IAppBuilder app) {
        app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/account/log-in/"),
            AuthenticationMode = AuthenticationMode.Active,
            CookieHttpOnly = true,
            CookieName = ".some-cookie-name",
            ExpireTimeSpan = TimeSpan.FromDays(1),
            LogoutPath = new PathString("/account/log-out/"),
            SlidingExpiration = true,
            ReturnUrlParameter = "continue"
        });
    }
}

I also have this line in global.asax::Application_Start method:

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

and these configuration in web.config:

<system.web>
  <authentication mode="None" />
  <httpModules>
    <remove name="FormsAuthenticationModule" />
    <remove name="RoleManager" />
  </httpModules>
</system.web>
<system.webServer>
  <validation validateIntegratedModeConfiguration="false" />
  <modules runAllManagedModulesForAllRequests="false">
    <remove name="FormsAuthenticationModule" />
    <remove name="RoleManager" />
  </modules>
</system.webServer>

and finally I'm running the application on a Windows 2008 R2 machine with IIS 7.5. Do you have any idea what should I do to make OWIN work correctly on my server, just like my local?

UPDATE: To be clear:

Assume I have these actions:

[AllowAnonymous]
public ActionResult AnonymousAction() { }

[Authorize]
public ActionResult UsersAction() { }

One for anonymous users, and another for logged-in users (which are well decorated with attributes). Anonymous users, can access AnonymousAction easily without any error or misbehavior. But when they (I mean Anonymous users) want to access UsersAction, instead of getting redirected to login page, they will see the window I mentioned above.


Solution

  • Well, it was really simple. According to @trailmax's answer (thanks to him), I realized that I should pay attention to the response's http-code. It was a 401 - Unauthorized code. So, I asked myself why is that? Until I found this answer. Then, the only thing I needed was creating the following attribute:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
            if (filterContext.HttpContext.Request.IsAuthenticated) {
                filterContext.Result = new HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
            } else {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }
    }