我正在使用Identityserver4进行多个应用程序的身份验证。它与MVC客户端配合得很好,但是我遇到了Web窗体的问题。 当我从IdentitysServer注销时,Webforms请求仍然保持已认证状态。 下面的WebForms启动类和相关的Identityserver4配置。
Identityserver4客户端配置:
new Client {
ClientId = "legacy_clients",
ClientName = "The Legacy Application",
AccessTokenType = AccessTokenType.Reference,
AllowedGrantTypes = GrantTypes.Implicit,
IdentityTokenLifetime = 120,
AccessTokenLifetime =30,
AllowAccessTokensViaBrowser = true,
//AllowOfflineAccess = true,
RedirectUris = new List<string> {
"http://localhost:4200/auth-callback",
"http://localhost:57227/signin-oidc",
},
RequireConsent = false,
PostLogoutRedirectUris = new List<string>
{
"http://localhost:4200/",
"http://localhost:57227/signout-callback-oidc",
},
AllowedCorsOrigins = new List<string> { "http://localhost:4200", "http://localhost:57227" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles"
},
}
WebForm启动:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = "Cookies",
ExpireTimeSpan = TimeSpan.FromMinutes(1),
SlidingExpiration = true
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
SignInAsAuthenticationType = "Cookies",
Authority = "https://localhost:44360",
ClientId = "legacy_client",
RedirectUri = "http://localhost:57227/signin-oidc",
PostLogoutRedirectUri = "http://localhost:57227/signout-callback-oidc",
ResponseType = "id_token token",
Scope = "openid profile roles",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var claims_to_exclude = new[]
{
"aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
};
var claims_to_keep =
n.AuthenticationTicket.Identity.Claims
.Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();
claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
if (n.ProtocolMessage.AccessToken != null)
{
claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
var userInfoClient = new UserInfoClient("https://localhost:44360/connect/userinfo");
var userInfoResponse = await userInfoClient.PostAsync(n.ProtocolMessage.AccessToken);
var userInfoClaims = userInfoResponse.Claims
.Where(x => x.Type!= "sub") // filter sub since we're already getting it from id_token
.Select(x => new System.Security.Claims.Claim(x.Type, x.Value));
claims_to_keep.AddRange(userInfoClaims);
}
var ci = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
"name", "role");
ci.AddClaims(claims_to_keep);
n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(
ci, n.AuthenticationTicket.Properties
);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
n.ProtocolMessage.IdTokenHint = id_token;
}
return Task.FromResult(0);
}
}
});
app.UseStageMarker(PipelineStage.Authenticate);
}
}
在网上使用:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
// webforms Code here.
var claims = ((System.Security.Claims.ClaimsPrincipal)User).Claims;
var subjectId = claims.Where(t=>t.Type== "sub").Select(t=>t.Value);
}
}
Request.IsAuthenticated最初为false,但是一旦我登录到Identityserver,它为true,就可以了。但是从Identityserver注销后,Web窗体仍显示Request.IsAuthenticatd为True。