使用ASP.NET核心2.0在OpenID和OAuth授权后清空声明

时间:2017-10-08 18:46:54

标签: asp.net oauth openid asp.net-core-2.0 claims

我已将已存在的项目迁移到新的核心2.0 using this guidance 除了使用OpenID和OAuth进行身份验证之外,几乎所有事情都非常好。

OpenID用于MS身份验证,而OAuth用于LinkedIn。

它将我重定向到MS登录页面(或在第二种情况下转到LinkedIn) 成功验证后,将我重定向回我的应用程序,但根本没有凭据。 User.Claims中的AccountController在此之后仍为空。

以下是Startup.cs中的代码:

    // in Configure()
    app.UseAuthentication();

    // in ConfigureServices()
    services.ConfigureApplicationCookie(options =>
        {
            options.ExpireTimeSpan = TimeSpan.FromDays(150);
            options.LoginPath = "/Account/Login";
            options.LogoutPath = "/Account/Logout";
        });

        services.AddAuthentication(
                opts =>
                {
                    opts.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    opts.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    opts.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    opts.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
            .AddCookie()
            .AddOpenIdConnect(AddAzureAuthOptions)
            .AddOAuth(Configuration["LinkedIn:AuthenticationScheme"], AddLinkedInAuthOptions);


    private void AddAzureAuthOptions(OpenIdConnectOptions options)
    {
        // Azure auth
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.Authority = Configuration["AzureAd:AadInstance"];
        options.ClientId = Configuration["AzureAd:ClientId"];
        options.ClientSecret = Configuration["AzureAd:ClientSecret"];
        options.SignedOutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"];
        options.GetClaimsFromUserInfoEndpoint = true;
        options.ResponseType = OpenIdConnectResponseType.IdToken;
    }

    private void AddLinkedInAuthOptions(OAuthOptions options)
    {
        // LinkedIn auth
        options.ClientId = Configuration["LinkedIn:ClientId"];
        options.ClientSecret = Configuration["LinkedIn:ClientSecret"];

        options.CallbackPath = new PathString(Configuration["LinkedIn:CallbackPath"]);

        options.AuthorizationEndpoint = Configuration["LinkedIn:AuthorizationEndpoint"];
        options.TokenEndpoint = Configuration["LinkedIn:TokenEndpoint"];
        options.UserInformationEndpoint = Configuration["LinkedIn:UserInformationEndpoint"];

        options.Events = new OAuthEvents
        {
            OnCreatingTicket = async contextLocal => await CreatingTicketHandler(contextLocal)
        };
    }

    private static async Task CreatingTicketHandler(OAuthCreatingTicketContext contextLocal)
    {
        var request = new HttpRequestMessage(HttpMethod.Get,
            contextLocal.Options.UserInformationEndpoint);
        request.Headers.Authorization =
            new AuthenticationHeaderValue("Bearer", contextLocal.AccessToken);
        request.Headers.Add("x-li-format", "json");

        var response = await contextLocal.Backchannel.SendAsync(request,
            contextLocal.HttpContext.RequestAborted);
        response.EnsureSuccessStatusCode();

        var user = JObject.Parse(await response.Content.ReadAsStringAsync());

        var userId = user.Value<string>("id");
        if (!string.IsNullOrEmpty(userId))
        {
            contextLocal.Identity.AddClaim(new Claim("linkedinid", userId, ClaimValueTypes.String,
                contextLocal.Options.ClaimsIssuer));
        }

        var formattedName = user.Value<string>("formattedName");
        if (!string.IsNullOrEmpty(formattedName))
        {
            contextLocal.Identity.AddClaim(new Claim("firstlastname", formattedName,
                ClaimValueTypes.String, contextLocal.Options.ClaimsIssuer));
        }

        var email = user.Value<string>("emailAddress");
        if (!string.IsNullOrEmpty(email))
        {
            contextLocal.Identity.AddClaim(new Claim("linkedinemail", email, ClaimValueTypes.String,
                contextLocal.Options.ClaimsIssuer));
        }
    }       

AccountController中的操作:

    [HttpGet]
    [AllowAnonymous]
    public IActionResult SignInExternal(string scheme, string uri)
    {
        if (User == null || !User.Identity.IsAuthenticated)
        {
            return Challenge(new AuthenticationProperties {RedirectUri = uri}, scheme);
        }


        return RedirectToAction("Index", "Home");
    } 

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> SignInExternalCallback(string type, string direct)
    {
        var socialNetwork =
            _socialNetworksService?.GetSocialNetwork(User.Claims.FirstOrDefault(x => x.Type.EndsWith(type))
                ?.Value);

        // if socialNetwork doesn't exist in DB redirects to external SignUp-s
        if (socialNetwork is null)
            return RedirectToAction(direct);

        await _signInManager.SignInAsync(socialNetwork.User, true);

        return RedirectToAction("Index", "Home");
    }

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> SignUpMicrosoft(string returnUrl = null)
    {
        var claims = User.Claims.ToList(); // claims are still empty
        var user = _sessionService.GetCurrentUser();

        if (user is null) // create user in system using passed Claims 
        {
            var firstName = claims.FirstOrDefault(x => x.Type == "givenname")?.Value;
            var lastName = claims.FirstOrDefault(x => x.Type == "surname")?.Value;

            await CreateNewUserViaExternalAccountHelperAsync(User.Identity.Name, firstName, lastName,
                User.Identity.Name, SocialNetworkType.Microsoft, "objectidentifier");
        }
        else // sign in User
        {           
            var id = claims.FirstOrDefault(x => x.Type == "objectidentifier")?.Value;               

            await SingInViaExternalAccountHelper(user, SocialNetworkType.Microsoft, id);
        }


        return RedirectToAction("Index", "Home");
    }


    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> SignUpLinkedIn()
    {
        var claims = User.Claims.ToList(); // claims are still empty

        var user = _sessionService.GetCurrentUser();

        var email = claims.FirstOrDefault(x => x.Type == "linkedinemail")?.Value ?? string.Empty;

        if (user is null) // create user in system using passed Claims 
        {
            var userName = claims.FirstOrDefault(x => x.Type == "firstlastname")
                ?.Value
                .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var firstName = userName?.FirstOrDefault();
            var lastName = userName?.LastOrDefault();

            await CreateNewUserViaExternalAccountHelperAsync(email,firstName, lastName, email,
                SocialNetworkType.LinkedIn, "linkedinid");
        }
        else // sign in as User
        {
            var userId = claims.FirstOrDefault(x => x.Type == "linkedinid")?.Value;

            await SingInViaExternalAccountHelper(user, SocialNetworkType.LinkedIn, userId);
        }

        return RedirectToAction("Index", "Home");
    }

    private async Task CreateNewUserViaExternalAccountHelperAsync(string email, string firstName,
        string lastName, string userName,
        SocialNetworkType type, string idType)
    {
        var newUser = new User
        {
            Activated = true,
            Email = email,
            EmailConfirmed = true,
            FirstName = firstName,
            LastName = lastName,
            Enabled = true,
            UserName = userName
        };

        var result = await _userManager.CreateAsync(newUser));

        if (result.Succeeded)
        {
            var currentUser = await _userManager.FindByNameAsync(newUser.UserName);

            await SingInViaExternalAccountHelper(currentUser, type,
                User.Claims.FirstOrDefault(x => x.Type.EndsWith(idType))?.Value);
        }
    }

    private async Task SingInViaExternalAccountHelper(User user, SocialNetworkType type, string id)
    {
        await _socialNetworksService.CreateSocialNetworkAsync(user, id, type);
        await _signInManager.SignInAsync(user, true);
    }

非常感谢任何回复。

0 个答案:

没有答案