0

I have two apps I'm working on. Both of them need to use both Windows authentication and anonymous access. so to do this, I edited the web.config to get rid of the authorization tag (with "deny users="?"") and only tagged a few actions with my custom authorization attribute. the trouble is, the server is "forgetting" me. so for instance, on the first app, one user reports that she has to attempt to access the control panel every other time she wants to edit. On the second one, I click login, I'm logged in, and then I click any other link (especially "save") and I'm logged out.

here's one of my custom authorization attributes:

public class AccountsAuthorizeITAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if(httpContext.User.Identity.IsAuthenticated == false)
        {
            return false;
        }

        if(httpContext.User.IsInRole("CT-IT"))
        {
            return true;
        }

        return false;
    }
}

and to log in, I just have this in my _layout:

@Html.ActionLink("Login", "Login", "Login", new { returnURL = HttpContext.Current.Request.RawUrl }, null)

with this login controller:

public class LoginController : Controller
{
    [AccountsAuthorizeIT]
    public ActionResult Login(string returnURL)
    {
        return Redirect(returnURL);
    }
}

What could cause this? Shouldn't my authentication be stored in the session variable, saved for (roughly) as long as the browser window is open? Do I need to tell the server to remember my data?

Adam R. Grey
  • 1,861
  • 17
  • 30
  • 1
    What are you using for Authentication? Forms, Membership, Identity? – Erik Philips Apr 07 '17 at 15:28
  • @ErikPhilips Windows? Is that "Membership" or "Identity"? – Adam R. Grey Apr 07 '17 at 15:29
  • 1
    authorization tag inside web.config is for ASP.NET Web Form. You should not use in ASP.NET MVC. Are you using Active Directory for authentication? Please show your login code. – Win Apr 07 '17 at 15:31
  • @Win edited question to include login, I guess I'm using active directory? Whatever the default is when you select "windows authentication" when creating the project. – Adam R. Grey Apr 07 '17 at 15:37
  • What is `CT-IT`? Is it Active Directory Group name? – Win Apr 07 '17 at 15:41
  • @Win Yes it is. – Adam R. Grey Apr 07 '17 at 15:42
  • Do you have a machinekey in your web.config file? – Salvador Guerrero Apr 07 '17 at 15:47
  • 1
    @SalvadorGuerrero no. What's a machinekey? – Adam R. Grey Apr 07 '17 at 15:48
  • 2
    Authentication is *NOT* stored in a session variable. Session should never be used for authentication, ever. It's insecure and unreliable, since sessions can be lost at any time (IIS does not guarantee they will stay active). Authentication is handled by a special authentication cookie, which is either temporary (not stored on disk) or persistent (is stored on disk). – Erik Funkenbusch Apr 07 '17 at 15:56
  • It's an encription key used to maintain sessions across IIS processes, if it's not configured your sessions will be forgotten if the IIS process is recycled Here's how to configure it on IIS UI and directly on the web.config file http://docs.orchardproject.net/en/latest/Documentation/Setting-up-a-machine-key/ – Salvador Guerrero Apr 07 '17 at 15:57
  • 1
    I also do not understand why you need a custom authorization attribute. All you have to do is use the standard `[Authorize(Role="CT-IT")]` and it does exactly what your custom attribute does. – Erik Funkenbusch Apr 07 '17 at 15:58
  • @ErikFunkenbusch I have another one that also checks another group, I just figured I'd make this one for consistency and show it instead of the other one for simplicity. – Adam R. Grey Apr 07 '17 at 16:00
  • 1
    Do not use web.config authorization with MVC and *ESPECIALLY* don't use web.config AND Attribute authorization at the same time. Read the reminder here: https://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-global-authentication-and-allow-anonymous – Erik Funkenbusch Apr 07 '17 at 16:04
  • @SalvadorGuerrero Ok, following that article I added a machine key. Didn't help the issue. – Adam R. Grey Apr 10 '17 at 12:42

1 Answers1

1

Shouldn't my authentication be stored in the session variable, saved for (roughly) as long as the browser window is open? Do I need to tell the server to remember my data?

I personally like to store them in Principle object as Claim using OWIN Cookie Middleware.

Here is the sample code. roleNames could be user's assigned Active Directory Group.

public void SignIn(User user, IList<string> roleNames)
{
    IList<Claim> claims = new List<Claim>
            {
                new Claim(ClaimTypes.Sid, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.UserName),
                new Claim(ClaimTypes.GivenName, user.FirstName),
                new Claim(ClaimTypes.Surname, user.LastName),
            };

    foreach (string roleName in roleNames)
    {
        claims.Add(new Claim(ClaimTypes.Role, roleName));
    }

    ClaimsIdentity identity = new ClaimsIdentity(claims, AuthenticationType);

    IOwinContext context = _context.Request.GetOwinContext();
    IAuthenticationManager authenticationManager = context.Authentication;

    authenticationManager.SignIn(identity);
}

Startup.cs

Then you register OWIN Cookie Middleware at start up.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "ApplicationCookie",
            LoginPath = new PathString("/Account/Login")
        });
    }
}

If you store them in Principle object, you won't even need custom attribute AccountsAuthorizeITAttribute.

Win
  • 61,100
  • 13
  • 102
  • 181
  • I tried adapting this to my code (using http://stackoverflow.com/questions/5309988/how-to-get-the-groups-of-a-user-in-active-directory-c-asp-net to find active directory groups, ignoring ClaimTypes.Sid and the other claim types that User doesn't provide, using "Windows" instead of "AuthenticationType" in ClaimsIdentity), but I couldn't find GetOwinContext on anything. Is it a package I need to install? – Adam R. Grey Apr 10 '17 at 12:37
  • You can look at all requires packages [here](https://github.com/WinLwinOoNet/AspNetMvcActiveDirectoryOwin/blob/master/src/Presentation/AspNetMvcActiveDirectoryOwin.Web.Common/packages.config). – Win Apr 10 '17 at 14:35
  • Great, I was able to install a few owin packages and get everything to compile. However, two problems: 1) whenever I start the app, no matter what page I'm trying to start to, it redirects itself to the login page and 2) the login page it redirects to for some reason redirects to itself so many times I get an error: "The request filtering module is configured to deny a request where the query string is too long." I tried putting a breakpoint in the login code, but it doesn't hit it. I guess I'm doomed to make a public version and a windows auth version. – Adam R. Grey Apr 10 '17 at 20:27
  • You need to place `[AllowAnonymous]` attribute on Login HttpGet method and HttpPost method. – Win Apr 10 '17 at 20:33
  • So doing this method means I lose the ability to have some areas public and some areas private? – Adam R. Grey Apr 11 '17 at 12:55
  • No. `[AllowAnonymous]` on action methods means you allows anonymous access to that specific action methods, even if you register other attributes on controller or globally elsewhere. – Win Apr 11 '17 at 13:25