身份服务器4使用MVC引用令牌

时间:2017-10-27 17:35:44

标签: access-token identityserver4

我正在使用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

3 个答案:

答案 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,无需身份验证即可创建新的引用令牌)。

现在我很困惑!