Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is OWIN's SignInAsync() not setting IsAuthenticated (or other authentication variables)?

I have a .NET, MVC 5, EF 6 project. We're connecting to an external project/database for authenticating users, so all we need to implement is login and logout methods, not normal CRUD methods. I know I have EF mapped correctly to the external database's tables; I can see it get the users.

I'm trying to use OWIN to authenticate so that I can use attributes like [Authorize] throughout the controller methods. I've been following this as my guide.

In Startup.Auth.cs I have:

    app.CreatePerOwinContext<CustomUserManager>(CustomUserManager.Create);
    app.CreatePerOwinContext<CustomSignInManager>(CustomSignInManager.Create);
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        {
            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)
            )
        },
        CookieSecure = CookieSecureOption.Always
    });

I also have classes implementing interfaces IUserStore<User>, UserManager<User>, and SignInManager<User, string>. My CustomUserStore has the following method implemented because the source says that's how it does logins. I implemented dummy methods for the other functions (i.e. DeleteAsync(), UpdateAsync(), etc.) that don't need to be implemented because we have read-only access to this external users db...

    public async Task<User> FindByIdAsync(string id)
    {
        using (ExternalDBContext context = new ExternalDBContext())
        {
            return await Task.Run(() =>
                context.Users.Where(u => u.Id == id).ToList().FirstOrDefault()
            );
        }
    }

Then in my AccountController.Login() I have:

        await CustomSignInManager.SignInAsync(model, true, true);
        return RedirectToAction("Index", "Dashboard");

But after SignInAsync(), User.Identity.IsAuthenticated is still false and therefore none of the authorize attributes won't work.

#1 Possible Problem: I'm wondering if the problem is with AuthenticationManager, which SignInManager relies on. Here's how I'm implementing it in Startup.Auth.cs:

public class CustomSignInManager : SignInManager<User, string>
{
    public CustomSignInManager(CustomUserManager userManager, IAuthenticationManager authenticationManager)
        : base(userManager, authenticationManager)
    {
    }
    public static CustomSignInManager Create(IdentityFactoryOptions<CustomSignInManager> options, IOwinContext context)
    {
        return new CustomSignInManager(context.GetUserManager<CustomUserManager>(), context.Authentication);
    }
}

It gets a Microsoft.Owin.Security.AuthenticationManager from the context.

So: do I need to do something else to implement authentication?

#2 Possible Problem: I notice my CustomUserManager has a property SupportsUserLogin = false. That property requires implementing IUserLoginStore. I don't want to implement yet another useless interface full of methods that I'm not using!

So: does it matter if SupportsUserLogin = false? Do I need to implement that interface or is there a way around this?

Summary: Overall this has gotten too complicated for a project where all I want to do is LOG THE USER IN. And out. I don't want to create/update/delete users. I just want to log a user in and have User.Identity.IsAuthenticated = true until they logout. So any ideas about how to backtrack to a simpler way of using Identity framework would be most greatly appreciated. My biggest question is whether I'm going down the right route at all.

Edit: I definitely don't want to do #2 (implement IUserLoginStore) because that is for doing external authentication.

like image 568
levininja Avatar asked Nov 09 '22 22:11

levininja


1 Answers

are you using https? if not remove this line: CookieSecure = CookieSecureOption.Always

also there is no need for IUserLoginStore (that is only for external auth like facebook) more info about that: here

side note: change Task.Factory.StartNew to Task.Run link

like image 66
pajics Avatar answered Nov 23 '22 22:11

pajics