我正在使用Identity server 4(使用实体框架进行配置)并使用引用令牌(AccessTokenType = 1)定义MVC客户端。我可以使用客户端和已定义的用户登录IS4并获取访问令牌(引用类型)。我知道这个令牌不包含声明,但我在Security.Claims.ClaimPrincipal中有所有声明。它是通过在IS4的场景请求后面做出声明吗?
我有两个主要问题:
1)我为MVC客户端设置访问令牌的生存时间为10分钟,cookie有效期为450小时。我希望10分钟后用户重定向到IS4上的登录页面,因为访问令牌已过期,但它没有发生
2)当我从数据库中删除PersistedGrants时,我仍然登录并可以看到MVC客户端,为什么? 我应该在MVC客户端的中间件上做什么来通过使用引用令牌来检查访问令牌吗? 我需要这个来强制用户再次登录所有登录的客户端。 这是我的MVC设置:
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
ExpireTimeSpan = TimeSpan.FromHours(750),
AutomaticChallenge = true
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(
new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:7010",
RequireHttpsMetadata = false,
ClientId = "MVC_Client",
ClientSecret = "MVC_Client",
ResponseType = "code id_token",
Scope =
{
Common.Constants.IdentityManagement.OpenIdScopeName,
Common.Constants.IdentityManagement.ProfileScopeName,
Common.Constants.IdentityManagement.EmailScopeName,
},
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true,
TokenValidationParameters =
new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role
},
Events = new OpenIdConnectEvents()
{
OnTicketReceived = OnTicketReceived
}
});
客户端有两种授权类型:hybrid,client_credentials
这是数据库中的客户端属性:
[AbsoluteRefreshTokenLifetime]: 60
[AccessTokenLifetime]: 60
[AccessTokenType]: 1
[AllowAccessTokensViaBrowser]: False
[AllowOfflineAccess]: True
[AllowPlainTextPkce]: False
[AllowRememberConsent]: True
[AlwaysIncludeUserClaimsInIdToken]: False
[AlwaysSendClientClaims]: False
[AuthorizationCodeLifetime]: 60
[ClientId]: MVC_Client
[ClientName]: MVC_Client
[ClientUri]: NULL
[EnableLocalLogin]: True
[Enabled]: True
[IdentityTokenLifetime]: 60
[IncludeJwtId]: False
[LogoUri]: NULL
[LogoutSessionRequired]: True
[LogoutUri]: NULL
[PrefixClientClaims]: True
[ProtocolType]: oidc
[RefreshTokenExpiration]: 60
[RefreshTokenUsage]: 1
[RequireClientSecret]: True
[RequireConsent]: False
[RequirePkce]: False
[SlidingRefreshTokenLifetime]: 60
[UpdateAccessTokenClaimsOnRefresh]: False
答案 0 :(得分:0)
我已经解决了类似的问题,并根据访问令牌的生命周期设置了cookie的生命周期,刷新访问令牌后,它将更新cookie。
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
...
SaveTokens = true,
UseTokenLifetime = false,
Events = new OpenIdConnectEvents()
{
OnTicketReceived = n => OnTicketReceived(n)
}
});
private Task OnTicketReceived(TicketReceivedContext n)
{
var accessTokenExpiresAt = n.Properties.Items[".Token.expires_at"];
n.Properties.ExpiresUtc = DateTimeOffset.Parse(accessTokenExpiresAt);
return Task.FromResult(0);
}
管理cookie的另一种方法是使用以下方法OnValidatePrincipal
:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = LastChangedValidator.ValidateAsync
}
});
public static class LastChangedValidator
{
public static async Task ValidateAsync(CookieValidatePrincipalContext context)
{
// Check if user is still valid
if (!isUserValid)
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(
CookieAuthenticationDefaults.AuthenticationScheme);
}
}
}
以下代码来自此处:https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?tabs=aspnetcore1x
答案 1 :(得分:0)
谢谢Jenan。
将Cookie到期设置为令牌到期工作。
我遇到的另一个问题是,当我从PersistedGrants中删除引用令牌并且在10分钟(访问令牌生存期)之后,cookie已过期,我希望该用户被重定向到登录页面。但MVC客户端转到IS并且IS在没有身份验证的情况下创建新的引用令牌。怎么可能?
在IdentityServer日志中,我看到了:
[Microsoft.AspNetCore.Hosting.Internal.WebHost] Request starting HTTP/1.1 GET http://localhost:7010/connect/authorize?client_id=IdentityManagement&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20profile%20email%20Roles%20IdentityManagement%20IdentityUsers&response_mode=form_post&nonce=636452284146749770.ZTk3YzFiM2QtYTQxMi00MGI3LWJjMGEtMWFkOGRhYTE0ZjE3NDhjZGE3MjMtYTczNS00Y2ZkLThhOTctNzAxYmM4NTY4MjE5&state=CfDJ8HzK9L_BsbZJtObgOKdlRawJPSBTZc1UETnT9osu2OIOojB6vxT7t7GjIBO2nf2TYngPk3u8EcDMk8o_dVUvj8VTaEQf0s1DvTUwaxZn93_TKv1waoFukeEBFwaSB1yWTbNq62dyYkLc6_fkiW4r16BwFyKpVEvaMmh2NGLUmfFiQ-7qj6f4VyR3pM0ydd7Ah8Vs6BIfXlyqtQJ4Ak4sR1jrcGO9-ViTWCFe2YN0M9-OWFluiFQOylh4quzwseYjjOgY0ruVCwK7Lw1pvVMewnn_f2uiXk7QXBz7TMYcp8kylbdgL5Vx0fSBrB67nKSER5m-gjPXNIky6FrBPSouqzw
[Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware] HttpContext.User merged via AutomaticAuthentication from authenticationScheme: "idsrv".
[Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware] AuthenticationScheme: "idsrv" was successfully authenticated.
[IdentityServer4.Hosting.IdentityServerMiddleware] Invoking IdentityServer endpoint: "IdentityServer4.Endpoints.AuthorizeEndpoint" for "/connect/authorize"
[Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware] AuthenticationScheme: "idsrv" was successfully authenticated.
为什么IdentityServer无需身份验证即可创建新的引用令牌。先前的参考令牌已从PersistedGrants中删除。
我这样做是为了强迫用户在紧急情况下再次登录(丢失设备,......)
答案 2 :(得分:0)
正确,我用它来设置IS cookie:
var props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddSeconds(120)
};
await HttpContext.Authentication.SignInAsync(userCredential.User.Id.ToString(), userCredential.User.UserName, props);
但我不想将其设置为与客户端cookie过期相同,因为它会影响SSO。此外,如果我将IS cookie设置为大于客户端cookie,则会发生其他问题(因为IS cookie是有效的IS,无需身份验证即可创建新的引用令牌)。
现在我很困惑!