我正在使用.NET Framework 4.7.2 MVC应用程序,它始终位于负载平衡器的后面,并且除非添加第二个MVC App实例,否则效果很好。
IdentityServer4本身正在使用数据保护,但是非核心客户端遇到此问题。
我找不到.NET框架的等效数据保护。有没有,或者我看到不同的东西?
如果我从负载均衡器中删除一个实例,它将再次起作用。最小工作示例
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
SlidingExpiration = true
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = identityServerUrl,
//Get this dynamically, register all possible values in IDS.
//https://github.com/IdentityServer/IdentityServer3/issues/1458
RedirectUri = redirectUrl,
PostLogoutRedirectUri = postLogoutRedirectUrl,
ResponseType = "code id_token",
Scope = scope,
SaveTokens = true,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
},
RequireHttpsMetadata = false,
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
UseTokenLifetime = false,
AuthenticationType = "OIDC",
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async tokenValidatedNotification =>
{
try
{
logger.LogTrace("Entering AuthorizationCodeReceived {authTicketIdentity} {response}",
tokenValidatedNotification.AuthenticationTicket.Identity, tokenValidatedNotification.Response.StatusCode);
var claimsToKeep = tokenValidatedNotification.AuthenticationTicket.Identity.Claims.ToList();
claimsToKeep.Add(new Claim("id_token", tokenValidatedNotification.ProtocolMessage.IdToken));
// use the code to get the access and refresh token
#pragma warning disable CS0618 // Type or member is obsolete
var tokenClient = new TokenClient($"{identityServerUrl}/connect/token", clientId, clientSecret);
#pragma warning restore CS0618 // Type or member is obsolete
TokenResponse tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
tokenValidatedNotification.ProtocolMessage.Code, redirectUrl);
if (tokenResponse.IsError)
{
throw new Exception($"Error authorizing user {tokenResponse.Error}, {tokenResponse.ErrorDescription}", tokenResponse.Exception);
}
// use the access token to retrieve claims from userinfo
#pragma warning disable CS0618 // Type or member is obsolete
var userInfoClient = new UserInfoClient($"{identityServerUrl}/connect/userinfo");
#pragma warning restore CS0618 // Type or member is obsolete
UserInfoResponse userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken)
.ConfigureAwait(false);
if (userInfoResponse.IsError)
{
throw new Exception(userInfoResponse.Error, userInfoResponse.Exception);
}
claimsToKeep.AddRange(userInfoResponse.Claims);
// create new identity
var claimsIdentity = new ClaimsIdentity(tokenValidatedNotification.AuthenticationTicket
.Identity
.AuthenticationType, "name", "role");
claimsIdentity.AddClaims(userInfoResponse.Claims);
claimsIdentity.AddClaims(claimsToKeep);
var user = claimsIdentity.Claims.FirstOrDefault(x => x.Type == "sub");
if (user != null && user.Value.Contains('@'))
{
var username = user.Value.Split('@')[0];
if (!string.IsNullOrEmpty(username))
{
//remove existing name claim
var removeClaim = claimsIdentity.Claims.ToList().FirstOrDefault(x => x.Type == "name");
if (removeClaim != null)
{
claimsIdentity.RemoveClaim(removeClaim);
}
//add username as name claim
claimsIdentity.AddClaim(new Claim("name", username.ToLower()));
}
}
tokenValidatedNotification.AuthenticationTicket = new AuthenticationTicket(
claimsIdentity,
tokenValidatedNotification.AuthenticationTicket.Properties);
await Task.FromResult(0);
}
catch (Exception ex)
{
logger.LogError(ex, "SecurityTokenValidated error {authTicketIdentity}, {responseStatus} (failure)", tokenValidatedNotification.AuthenticationTicket.Identity, tokenValidatedNotification.Response.StatusCode);
throw;
}
},
RedirectToIdentityProvider = async redirectToIdpNotification =>
{
try
{
if (!BrowserSupportService.isBrowserSupported())
{
redirectToIdpNotification.Response.Redirect("/browserNotSupported");
redirectToIdpNotification.HandleResponse();
}
else
{
// if signing out, add the id_token_hint
if (redirectToIdpNotification.ProtocolMessage.RequestType ==
OpenIdConnectRequestType.Logout)
{
Claim idTokenHint =
redirectToIdpNotification.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
redirectToIdpNotification.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
redirectToIdpNotification.ProtocolMessage.PostLogoutRedirectUri =
postLogoutRedirectUrl;
redirectToIdpNotification.Options.PostLogoutRedirectUri = postLogoutRedirectUrl;
}
if (redirectToIdpNotification.ProtocolMessage.RequestType ==
OpenIdConnectRequestType.Authentication
&& IsAjaxRequest(redirectToIdpNotification.Request) &&
redirectToIdpNotification.Response.StatusCode == (int) HttpStatusCode.Unauthorized)
{
redirectToIdpNotification.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
redirectToIdpNotification.HandleResponse();
}
}
await Task.FromResult(0);
}
catch (Exception ex)
{
logger.LogError(ex, "RedirectToIdentityProvider error");
throw;
}
}
}
});
日志文件的相关部分
IdentityServer logs are successful, no errors/warnings during this.
问题,我正在使用.NET Framework 4.7.2 MVC应用程序,它始终位于负载平衡器的后面,并且除非我添加第二个MVC App实例,否则效果很好。 IdentityServer4本身正在使用数据...