How to pass information from OnAuthenticated event to a controller and SignIn?

后端 未结 1 783
伪装坚强ぢ
伪装坚强ぢ 2021-02-04 21:42

As I\'ve found out here, I can\'t call

HttpContext.GetOwinContext().Authentication.SignIn(...)

in FacebookAuthenticationProvider OnAuthe

1条回答
  •  醉话见心
    2021-02-04 22:15

    I found a way to do this by looking at this answer and figuring out what I could do.

    Using Claims I can add all values retrieved from Facebook and throw into identity claims.

    OnAuthenticated = (context) =>
    {
        const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
    
        var rawUserObjectFromFacebookAsJson = context.User;
    
        context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook"));
        foreach (var x in context.User)
        {
            var claimType = string.Format("urn:facebook:{0}", x.Key);
            string claimValue = x.Value.ToString();
            if (!context.Identity.HasClaim(claimType, claimValue))
                context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, XmlSchemaString, "Facebook"));
    
        }
    
        return Task.FromResult(0);
    }
    

    Then on my controller I can get that identity by using this

    ClaimsIdentity identity = await HttpContext.GetOwinContext().Authentication
        .GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
    

    Then I will have on my action

    [AllowAnonymous]
    public async Task ExternalLoginCallback(string returnUrl)
    {
        ClaimsIdentity identity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
    
        var user = new IdentityUser()
        {
            Id = identity.GetUserId(),
            UserName = identity.Name,
        };
    
        await LoginAsync(user, identity);
    
        if (!identity.IsAuthenticated)
        {
            return RedirectToAction("Login");
        }
    
        return RedirectToAction("Index", "Home");
    }
    

    And my LoginAsync method

    private async Task LoginAsync(IdentityUser user, ClaimsIdentity identity)
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    
        // I can't just use the identity I got on Facebook
        // I need to create this one, or else it will not signin properly
        // The authentication type has to be ApplicationCookie and the property
        // is readonly, so...
        var userIdentity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    
        // now we have to transfer the claims, adding a check to avoid duplicates
        foreach (var claim in identity.Claims)
        {
            if (!userIdentity.HasClaim(c => c.Type == claim.Type))
                userIdentity.AddClaim(claim);
        }
    
        // then it will signin successfully
        AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, userIdentity);
    }
    

    Then I can access

    HttpContext.GetOwinContext().Authentication.User.Claims
    

    at any time and retrieve what I need.

    0 讨论(0)
提交回复
热议问题