我已将已存在的项目迁移到新的核心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);
}
非常感谢任何回复。