在本周我试图让我的客户端连接到我的IdentityServer 4。
在IdentityServer上,我实现了IProfileService,为用户设置了一些静态声明。
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _userClaimsPrincipalFactory.CreateAsync(user);
var claims = principal.Claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
context.IssuedClaims = claims;
var claims2 = new List<Claim>
{
new Claim("role", "JustSpend.Employee"),
new Claim("role", "JustSpend.Administrator"),
new Claim("fullName", string.Format("{0} {1}", user.FirstName, user.LastName)),
new Claim("canAccess", "JustSpend"),
new Claim("canAccess", "APRA"),
new Claim("canAccess", "SFVO")
};
context.IssuedClaims.AddRange(claims2);
}
在MVC 4客户端,我有以下配置:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "NIC Identity",
Authority = "http://localhost:5000", //ID Server
ClientId = "JSpend",
ResponseType = "id_token code",
SignInAsAuthenticationType = "Cookies",
RedirectUri = "http://localhost:57895/signin-oidc", //URL of website
PostLogoutRedirectUri = "http://localhost:57895/",
Scope = "openid profile offline_access",
TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name", RoleClaimType = "role" },
ClientSecret = "secret",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
var discoveryClient = new DiscoveryClient("http://localhost:5000");
var doc = await discoveryClient.GetAsync();
// use the code to get the access and refresh token
var tokenClient = new TokenClient(
doc.TokenEndpoint,
"JSpend",
"secret");
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
n.Code, n.RedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
// use the access token to retrieve claims from userinfo
var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint);
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
// create new identity
var id = n.AuthenticationTicket.Identity;
//id.AddClaims(userInfoResponse.Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
n.AuthenticationTicket.Properties);
},
RedirectToIdentityProvider = n =>
{
// if signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
在userInfoResponse中检索索赔都很好。用户登录后,将重定向到AccountController(ExternalLoginCallback)。但索赔根本没有映射到控制器中的用户。 ExternalLoginCallback方法:
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// Sign in the user with this external login provider if the user already has a login
var result = await _signInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
case SignInStatus.Failure:
default:
// If the user does not have an account, then prompt the user to create an account
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
}
}
谁能帮助我?我整个星期都在寻找解决方案,如果我谷歌,所有的搜索结果都会变成紫色(如访问过)......