0
votes

Just started using OWIN and ASP.NET MVC 5.

I want to get external logins working without persisting the users data.

At the moment I can get an authenticated response from Facebook and I can see all the claims, I even get the Application Cookie but the user in the user context is no the same Identity as the one I signed in.

The following is the code I have so far:

OWIN Startup

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            AuthenticationMode = AuthenticationMode.Passive,
            LoginPath = new PathString("/Login"),
            LogoutPath = new PathString("/Logout"),
        });
        app.UseExternalSignInCookie();
        var facebookAuthenticationOptions = new FacebookAuthenticationOptions
            {
                AppId = "XXX", AppSecret = "XXX",
            };

        facebookAuthenticationOptions.Scope.Add("email");

        app.UseFacebookAuthentication(facebookAuthenticationOptions);
    }
}

Controller

public class LandingPageController : Controller
{
    public ActionResult Index()
    {
        IAuthenticationManager authenticationManager = HttpContext.GetOwinContext().Authentication;

        //All I ever get is a WindowsPrincipal with an IsAuthenticated = false
        var identity = System.Web.HttpContext.Current.User as ClaimsPrincipal;
        var identity2 = ClaimsPrincipal.Current;
        var claimsPrincipal = authenticationManager.User ?? new ClaimsPrincipal();
        ...
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl = "/")
    {
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "LandingPage", new { loginProvider = provider, ReturnUrl = returnUrl }));
    }

    public async Task<RedirectResult> ExternalLoginCallback(string loginProvider, string returnUrl)
    {
        var authResult = await authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);

        authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);

        authentication.SignIn(new AuthenticationProperties() { IsPersistent = false }, new ClaimsIdentity(authResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie));
            return Redirect(returnUrl);
    }

    public class ChallengeResult : HttpUnauthorizedResult
    {
        public ChallengeResult(string provider, string redirectUrl)
        {
            LoginProvider = provider;
            RedirectUrl = redirectUrl;
        }

        public string LoginProvider { get; set; }
        public string RedirectUrl { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = RedirectUrl }, LoginProvider);
        }
    }

When I login with Facebook I get an Application Cookie but the user in the context is never authenticated and I don't get my claims. What have I missed?

1

1 Answers

2
votes

Seems I made a mistake with the two Cookie configurations. The external cookie uses and AuthenticationMode of Passive by default. I had also used the same when setting up Cookie Authentication. The application cookie needs to use Active.

Changing the OWIN configuration to the following got everything working.

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    AuthenticationMode = AuthenticationMode.Active,
    LoginPath = new PathString("/Login"),
    LogoutPath = new PathString("/Logout"),
});