ASP.NET 核心 LinkedIn 身份验证未获取数据

ASP.NET Core LinkedIn Authentication Not Getting Data

我正在我的 ASP.NET 核心应用程序中实施 LinkedIn 身份验证,但由于某种原因,我没有从 LinkedIn 获得任何数据。我哪里出错了?

在 Startup.cs 的 ConfigureServices 中,我有以下内容:

            services.AddMvc(options =>
            {
                options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));
            });

            services.AddAuthentication(options =>
            {
                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            });

在 Startup.cs 的 Configure 中,我有以下代码:

app.AuthenticationForMyApp(
                Configuration["linkedInClientId"],
                Configuration["linkedInClientSecret"],
                Configuration["linkedInCallback"]);

我的代码在 AuthenticationForMyApp 中看起来像这样 class:

public static void AuthenticationForMyApp(this IApplicationBuilder app, string linkedInClientId, string linkedInSecret, string linkedInCallback)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
                LoginPath = new PathString("/login"),
                AccessDeniedPath = new PathString("/unauthorized"),
                AutomaticAuthenticate = true,
                AutomaticChallenge = true
            });

            app.UseOAuthAuthentication(new OAuthOptions()
            {
                AuthenticationScheme = "LinkedIn",
                ClientId = linkedInClientId,
                ClientSecret = linkedInSecret,
                CallbackPath = linkedInCallback,
                AuthorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization",
                TokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken",
                UserInformationEndpoint = "https://api.linkedin.com/v1/people/~:(id,formatted-name,email-address,picture-url)",
                Scope = { "r_basicprofile", "r_emailaddress" },
                Events = new OAuthEvents()
                {
                    OnCreatingTicket = OnCreatingTicketLinkedInCallback,
                    OnTicketReceived = OnTicketReceivedCallback
                }
            });

        }
        private static Task OnCreatingTicketLinkedInCallback(OAuthCreatingTicketContext ctx)
        {
            var token = ctx.AccessToken;

            // *** Here ctx.User has no data about the user!!!
            var firstName = ctx.User["first_name"];
            var lastName = ctx.User["last_name"];
            var gender = ctx.User["gender"];
            var email = ctx.User["email"];
            var identity = ctx.Identity as ClaimsIdentity;

            if (firstName != null)
            {
                identity.AddClaim(new Claim(ClaimTypes.GivenName, firstName.ToString(), ClaimValueTypes.String, "LinkedIn"));
            }
            if (lastName != null)
            {
                identity.AddClaim(new Claim(ClaimTypes.Surname, lastName.ToString(), ClaimValueTypes.String, "LinkedIn"));
            }
            if (email != null)
            {
                identity.AddClaim(new Claim(System.Security.Claims.ClaimTypes.Email, email.ToString(), ClaimValueTypes.String, "LinkedIn"));
            }
            if (gender != null)
            {
                identity.AddClaim(new Claim(ClaimTypes.Gender, gender.ToString(), ClaimValueTypes.String, "LinkedIn"));
            }

            identity.AddClaim(new Claim("linkedin.token", token));

            return Task.FromResult(true);
        }
        private static Task OnTicketReceivedCallback(TicketReceivedContext ctx)
        {
            var identity = ctx.Principal.Identity as ClaimsIdentity;
            if (identity == null)
            {
                ctx.ReturnUri = "/unauthorized";
            }
            else
            {
                if (ctx.Properties.Items.ContainsKey("returnUrl"))
                {
                    ctx.ReturnUri += "?returnUrl=" + ctx.Properties.Items["returnUrl"];
                }
            }
            return Task.FromResult(true);
        }

按原样使用 OAuth2 通用中间件时,永远不会预先填充 OAuthCreatingTicketContext.User,因为您可以发送 "userinfo" 请求以从远程 OAuth2 提供程序检索用户配置文件。

更新 OnCreatingTicketLinkedInCallback 以向 LinkedIn 的用户信息端点发送 HTTP 请求并检索您需要的 JSON 响应或切换到 aspnet-contrib LinkedIn middleware that will do that for you, as suggested by @Tratcher.