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.
我正在我的 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.