使用ASP.NET core 2.0进行OpenID和OAuth授权后的空声明
我已经将已经存在的项目迁移到新的Core2.0 除了使用OpenID和OAuth进行身份验证之外,几乎所有的事情都是绝对好的 OpenID用于MS auth,OAuth-用于LinkedIn 它会将我重定向到MS登录页面(或者在第二种情况下重定向到LinkedIn) 认证成功后,我将重定向回我的应用程序,但根本没有凭据。使用ASP.NET core 2.0进行OpenID和OAuth授权后的空声明,asp.net,oauth,openid,asp.net-core-2.0,claims,Asp.net,Oauth,Openid,Asp.net Core 2.0,Claims,我已经将已经存在的项目迁移到新的Core2.0 除了使用OpenID和OAuth进行身份验证之外,几乎所有的事情都是绝对好的 OpenID用于MS auth,OAuth-用于LinkedIn 它会将我重定向到MS登录页面(或者在第二种情况下重定向到LinkedIn) 认证成功后,我将重定向回我的应用程序,但根本没有凭据。 AccountController中的User.声明在此之后仍然为空 这是我在Startup.cs中的代码: // in Configure() app.Use
AccountController
中的User.声明在此之后仍然为空
这是我在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));
}
}
//在Configure()中
app.UseAuthentication();
//在ConfigureServices()中
services.configureApplicationOK(选项=>
{
options.ExpireTimeSpan=TimeSpan.FromDays(150);
options.LoginPath=“/Account/Login”;
options.LogoutPath=“/Account/Logout”;
});
services.AddAuthentication(
选项=>
{
opts.DefaultChallengeScheme=CookieAuthenticationDefaults.AuthenticationScheme;
opts.DefaultSignenscheme=CookieAuthenticationDefaults.AuthenticationScheme;
opts.DefaultSignOutScheme=CookieAuthenticationDefaults.AuthenticationScheme;
opts.DefaultScheme=CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(AddAzureAuthOptions)
.AddOAuth(配置[“LinkedIn:AuthenticationScheme”]、AddLinkedInAuthOptions);
私有void AddAzureAuthOptions(OpenIdConnectOptions)
{
//Azure认证
options.signnscheme=CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority=Configuration[“AzureAd:AadInstance”];
options.ClientId=配置[“AzureAd:ClientId”];
options.ClientSecret=配置[“AzureAd:ClientSecret”];
options.SignedOutRedirectUri=配置[“AzureAd:PostLogoutRedirectUri”];
options.GetClaimsFromUserInfoEndpoint=true;
options.ResponseType=OpenIdConnectResponseType.IdToken;
}
私有void AddLinkedInAuthOptions(OAuthOptions选项)
{
//LinkedIn认证
options.ClientId=配置[“LinkedIn:ClientId”];
options.ClientSecret=配置[“LinkedIn:ClientSecret”];
options.CallbackPath=新路径字符串(配置[“LinkedIn:CallbackPath”]);
options.AuthorizationEndpoint=配置[“LinkedIn:AuthorizationEndpoint”];
options.TokenEndpoint=配置[“LinkedIn:TokenEndpoint”];
options.UserInformationEndpoint=配置[“LinkedIn:UserInformationEndpoint”];
options.Events=新的OAuthEvents
{
OnCreatingTicket=async contextLocal=>Wait CreatingTicketHandler(contextLocal)
};
}
专用静态异步任务CreatingTicketHandler(OAuthCreatingTicketContext contextLocal)
{
var请求=新的HttpRequestMessage(HttpMethod.Get,
contextLocal.Options.UserInformationEndpoint);
request.Headers.Authorization=
新的AuthenticationHeaderValue(“承载者”,contextLocal.AccessToken);
添加(“x-li-format”、“json”);
var response=await contextLocal.Backchannel.SendAsync(请求,
contextLocal.HttpContext.RequestAborted);
response.EnsureSuccessStatusCode();
var user=JObject.Parse(wait response.Content.ReadAsStringAsync());
var userId=user.Value(“id”);
如果(!string.IsNullOrEmpty(userId))
{
contextLocal.Identity.AddClaim(新声明(“linkedinid”、userId、ClaimValueTypes.String、,
contextLocal.Options.ClaimsIssuer);
}
var formattedName=user.Value(“formattedName”);
如果(!string.IsNullOrEmpty(formattedName))
{
contextLocal.Identity.AddClaim(新声明(“firstlastname”),formattedName,
ClaimValueTypes.String、contextLocal.Options.ClaimsIssuer));
}
var email=user.Value(“emailAddress”);
如果(!string.IsNullOrEmpty(电子邮件))
{
contextLocal.Identity.AddClaim(新声明(“linkedinemail”、电子邮件、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);
}
[HttpGet]
[异名]
公共IActionResult符号内部(字符串方案、字符串uri)
{
if(User==null | |!User.Identity.IsAuthenticated)
{
返回质询(新的AuthenticationProperties{RedirectUri=uri},scheme);
}
返回重定向到操作(“索引”、“主页”);
}
[HttpGet]
[异名]
公共异步任务符号TernalCallback(字符串类型,字符串直接)
{
var社会网络=
_socialNetworksService?.GetSocialNetwork(User.Claims.FirstOrDefault(x=>x.Type.EndsWith(Type))
?.价值);
//如果数据库中不存在社交网络,则重定向到外部注册
if(社交网络为空)
返回重定向到操作(直接);
wait _signInManager.SignInAsync(socialNetwork.User,true);
返回重定向到操作(“索引”、“主页”);
}
[HttpGet]
[异名]
公共异步任务注册Microsoft(字符串返回URL=null)
{
var claims=User.claims.ToList();//声明仍然为空
var user=_sessionService.GetCurrentUser();
if(user为null)//使用传递的声明在系统中创建用户
{
var firstName=claims.FirstOrDefault(x=>x.Type==“givenname”)?.Value;
var lastName=claims.FirstOrDefault(x=>x.Type==“姓氏”)?.Value;
等待CreateNewUserViaExternalAccountHelperAsync(User.Identity.Name、firstName、lastName、,
User.Identity.Name,SocialNetworkType.Microsoft,“objectidentifier”);
}
else//登录