令牌吊销后,connect / userinfo端点应该工作吗?

时间:2019-05-14 10:44:56

标签: c# jwt identityserver4 access-token

我正在使用IdentityServer4进行基于令牌的用户登录

用户登录后,我得到了access_tokenrefresh_token

当用户尝试注销时,我将其称为IdentityServer4的/connect/revocation端点

但是即使在令牌被吊销之后,当我调用/connect/userinfo端点时,我仍然可以获得用户信息。

我应该不会出错吗?

这是我实施RevokeToken

的方式
    protected async Task RevokeRefreshToken(string refreshToken)
    {
        var httpClient = new HttpClient();
        var refreshTokenRevokeResponse = await httpClient.RevokeTokenAsync(new TokenRevocationRequest
        {
            Address = identityServer.IdpRevocationEndPoint,
            ClientId = identityServer.IdpClientId,
            ClientSecret = identityServer.IdpClientSecret,
            Token = refreshToken,
            TokenTypeHint = "refresh_token"
        }).ConfigureAwait(false);
        if (refreshTokenRevokeResponse.IsError)
        {
            Utils.Log(refreshTokenRevokeResponse.Error, refreshTokenRevokeResponse.Exception);
        }
    }

    protected async Task RevokeAccessToken(string accessToken)
    {
        var httpClient = new HttpClient();
        var accessTokenRevokeResponse = await httpClient.RevokeTokenAsync(new TokenRevocationRequest
        {
            Address = identityServer.IdpRevocationEndPoint,
            ClientId = identityServer.IdpClientId,
            ClientSecret = identityServer.IdpClientSecret,
            Token = accessToken,               
        }).ConfigureAwait(false);
        if (accessTokenRevokeResponse.IsError)
        {
            Utils.Log(accessTokenRevokeResponse.Error, accessTokenRevokeResponse.Exception);
        }
    }

先调用撤销的函数先调用RevokeRefreshToken(string refreshToken),然后再调用RevokeAccessToken(string accessToken) 这是identityserver

中的客户端配置
       new Client
        {
            ClientId = "client_foo",
            ClientName = "foo client",
            ClientSecrets =
            {
                new Secret("secret".ToSha256())
            },
            AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
            AccessTokenLifetime = 3600,
            IdentityTokenLifetime = 3600,
            AllowOfflineAccess = true,
            RequirePkce = false,
            RequireClientSecret = false,
            RequireConsent = false,
            Enabled = true,
            RedirectUris = redirectUris,
            PostLogoutRedirectUris = postLogoutRedirectUris,
            AllowedCorsOrigins = allowedCorsOrigins,
            AlwaysIncludeUserClaimsInIdToken = true,
            UserSsoLifetime = 3600,
            RefreshTokenExpiration = TokenExpiration.Absolute,
            RefreshTokenUsage = TokenUsage.ReUse,
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "firstName",
                "lastName",
                "emailId",
            }
        }

这是IdentityServer上的日志文件

2019-05-14 12:25:28.950 +02:00 [DBG] Start discovery request
2019-05-14 12:26:19.370 +02:00 [DBG] Request path /connect/revocation matched to endpoint type Revocation
2019-05-14 12:26:19.383 +02:00 [DBG] Endpoint enabled: Revocation, successfully created handler: IdentityServer4.Endpoints.TokenRevocationEndpoint
2019-05-14 12:26:19.383 +02:00 [INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenRevocationEndpoint for /connect/revocation
2019-05-14 12:26:19.389 +02:00 [DBG] Start revocation request.
2019-05-14 12:26:19.389 +02:00 [DBG] Start client validation
2019-05-14 12:26:19.389 +02:00 [DBG] Start parsing Basic Authentication secret
2019-05-14 12:26:19.390 +02:00 [DBG] Start parsing for secret in post body
2019-05-14 12:26:19.391 +02:00 [DBG] Parser found secret: PostBodySecretParser
2019-05-14 12:26:19.391 +02:00 [DBG] Secret id found: client_foo
2019-05-14 12:26:19.392 +02:00 [DBG] client configuration validation for client client_foo succeeded.
2019-05-14 12:26:19.392 +02:00 [DBG] Public Client - skipping secret validation success
2019-05-14 12:26:19.405 +02:00 [DBG] Client validation success
2019-05-14 12:26:19.410 +02:00 [DBG] Token type hint found in request: refresh_token
2019-05-14 12:26:19.410 +02:00 [DBG] ValidateRequestAsync result: IdentityServer4.Validation.TokenRevocationRequestValidationResult
2019-05-14 12:26:19.426 +02:00 [DBG] Refresh token revoked
2019-05-14 12:26:19.432 +02:00 [INF] Token successfully revoked
2019-05-14 12:27:06.311 +02:00 [DBG] Request path /connect/revocation matched to endpoint type Revocation
2019-05-14 12:27:06.324 +02:00 [DBG] Endpoint enabled: Revocation, successfully created handler: IdentityServer4.Endpoints.TokenRevocationEndpoint
2019-05-14 12:27:06.325 +02:00 [INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenRevocationEndpoint for /connect/revocation
2019-05-14 12:27:06.325 +02:00 [DBG] Start revocation request.
2019-05-14 12:27:06.325 +02:00 [DBG] Start client validation
2019-05-14 12:27:06.325 +02:00 [DBG] Start parsing Basic Authentication secret
2019-05-14 12:27:06.325 +02:00 [DBG] Start parsing for secret in post body
2019-05-14 12:27:06.350 +02:00 [DBG] Parser found secret: PostBodySecretParser
2019-05-14 12:27:06.350 +02:00 [DBG] Secret id found: client_foo
2019-05-14 12:27:06.350 +02:00 [DBG] client configuration validation for client client_foo succeeded.
2019-05-14 12:27:06.350 +02:00 [DBG] Public Client - skipping secret validation success
2019-05-14 12:27:06.350 +02:00 [DBG] Client validation success
2019-05-14 12:27:06.350 +02:00 [DBG] ValidateRequestAsync result: IdentityServer4.Validation.TokenRevocationRequestValidationResult
2019-05-14 12:27:06.353 +02:00 [DBG] reference_token grant with value: eyJhbGciOiJSUzI1NiIsImtpZCI6ImY2YWM5MmZiOTlhNzRhYzcyMTFjYTE5ZjE3YTNlMjQyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1NTc4Mjk1MjMsImV4cCI6MTU1NzgzMzEyMywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNjciLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo0NDM2Ny9yZXNvdXJjZXMiLCJjbGllbnRfaWQiOiJlcEliZUNsaWVudFNlcnZlclNpZGUiLCJzdWIiOiIxNzI5IiwiYXV0aF90aW1lIjoxNTU3ODI5NTIxLCJpZHAiOiJsb2NhbCIsImVtYWlsIjoiYmtjQG9ubS5kZSIsImZpcnN0TmFtZSI6IkJpcGxvdiIsImxhc3ROYW1lIjoiS0MiLCJsYW5ndWFnZSI6IkUiLCJsZXR0ZXJHcmVldGluZyI6Ik1vbnNpZXVyIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.ZkJU1rYHJYOjgK3_NKcKHfcoDjT1E8iOft1qXw2_1xpHYB2oKM9CosXNuAJ52VmSDXbXIKoLTDvPKl5UXs4ZwO5rGwwFYGyel-tXiAz_mLwSEZuO3tq2c5b7tehhDndQBu7Pu--JeQdkruhMx9NenCwqLXK5dewTNnH7WpnolHvzyLWhbioBg5WTAEgiIQYLOi_G5pBHUwo_RlpihLwPHYzkocv4vIjKTTV26pcLryP3sKQ7btsv7H6htFrx42Nppi28cRIbcxc_jTLqbriB_HNgyBD_W7qRZ6CDnmYWTJdAqJiYGbUcu0SYXN0-2HrI71lXJhsoJ4lMxki8RQDsqA not found in store.
2019-05-14 12:27:06.353 +02:00 [DBG] refresh_token grant with value: eyJhbGciOiJSUzI1NiIsImtpZCI6ImY2YWM5MmZiOTlhNzRhYzcyMTFjYTE5ZjE3YTNlMjQyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1NTc4Mjk1MjMsImV4cCI6MTU1NzgzMzEyMywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNjciLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo0NDM2Ny9yZXNvdXJjZXMiLCJjbGllbnRfaWQiOiJlcEliZUNsaWVudFNlcnZlclNpZGUiLCJzdWIiOiIxNzI5IiwiYXV0aF90aW1lIjoxNTU3ODI5NTIxLCJpZHAiOiJsb2NhbCIsImVtYWlsIjoiYmtjQG9ubS5kZSIsImZpcnN0TmFtZSI6IkJpcGxvdiIsImxhc3ROYW1lIjoiS0MiLCJsYW5ndWFnZSI6IkUiLCJsZXR0ZXJHcmVldGluZyI6Ik1vbnNpZXVyIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.ZkJU1rYHJYOjgK3_NKcKHfcoDjT1E8iOft1qXw2_1xpHYB2oKM9CosXNuAJ52VmSDXbXIKoLTDvPKl5UXs4ZwO5rGwwFYGyel-tXiAz_mLwSEZuO3tq2c5b7tehhDndQBu7Pu--JeQdkruhMx9NenCwqLXK5dewTNnH7WpnolHvzyLWhbioBg5WTAEgiIQYLOi_G5pBHUwo_RlpihLwPHYzkocv4vIjKTTV26pcLryP3sKQ7btsv7H6htFrx42Nppi28cRIbcxc_jTLqbriB_HNgyBD_W7qRZ6CDnmYWTJdAqJiYGbUcu0SYXN0-2HrI71lXJhsoJ4lMxki8RQDsqA not found in store.
2019-05-14 12:27:06.353 +02:00 [INF] No matching token found
2019-05-14 12:28:49.765 +02:00 [DBG] CORS request made for path: /.well-known/openid-configuration from origin: https://localhost
2019-05-14 12:28:49.765 +02:00 [DBG] Client list checked and origin: https://localhost is allowed
2019-05-14 12:28:49.765 +02:00 [DBG] CorsPolicyService allowed origin: https://localhost
2019-05-14 12:28:49.765 +02:00 [DBG] Request path /.well-known/openid-configuration matched to endpoint type Discovery
2019-05-14 12:28:49.765 +02:00 [DBG] Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
2019-05-14 12:28:49.765 +02:00 [INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
2019-05-14 12:28:49.765 +02:00 [DBG] Start discovery request
2019-05-14 12:29:23.761 +02:00 [DBG] Request path /connect/userinfo matched to endpoint type Userinfo
2019-05-14 12:29:23.775 +02:00 [DBG] Endpoint enabled: Userinfo, successfully created handler: IdentityServer4.Endpoints.UserInfoEndpoint
2019-05-14 12:29:23.775 +02:00 [INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.UserInfoEndpoint for /connect/userinfo
2019-05-14 12:29:23.780 +02:00 [DBG] Start userinfo request
2019-05-14 12:29:23.785 +02:00 [DBG] Bearer token found in header
2019-05-14 12:29:23.811 +02:00 [DBG] client configuration validation for client client_foo succeeded.
2019-05-14 12:29:23.814 +02:00 [DBG] client configuration validation for client client_foo succeeded.
2019-05-14 12:29:24.722 +02:00 [DBG] Calling into custom token validator: IdentityServer4.Validation.DefaultCustomTokenValidator
2019-05-14 12:29:24.723 +02:00 [DBG] Token validation success
{"ClientId":null,"ClientName":null,"ValidateLifetime":true,"AccessTokenType":"Jwt","ExpectedScope":"openid","TokenHandle":null,"JwtId":null,"Claims":{"nbf":1557829523,"exp":1557833123,"iss":"https://localhost:44367","aud":"https://localhost:44367/resources","client_id":"client_foo","sub":"1729","auth_time":1557829521,"idp":"local","email":"foo@foo.com","firstName":"foo","lastName":"bar","language":"E","letterGreeting":"Monsieur","scope":["openid","profile","offline_access"],"amr":"pwd"},"$type":"TokenValidationLog"}
2019-05-14 12:29:25.622 +02:00 [DBG] Creating userinfo response
2019-05-14 12:29:25.626 +02:00 [DBG] Scopes in access token: openid profile offline_access
2019-05-14 12:29:25.628 +02:00 [DBG] Scopes in access token: openid profile offline_access
2019-05-14 12:29:25.630 +02:00 [DBG] Requested claim types: sub name family_name given_name middle_name nickname preferred_username profile picture website gender birthdate zoneinfo locale updated_at offline_access
2019-05-14 12:29:25.630 +02:00 [DBG] Scopes in access token: openid profile offline_access
2019-05-14 12:29:26.484 +02:00 [INF] Profile service returned the following claim types: sub email firstName lastName language letterGreeting

1 个答案:

答案 0 :(得分:0)

这里没有什么要注意的:

  1. 无法撤销JWT
  2. 只能撤销参考令牌

考虑,您有两个客户:“ A”和“ B”。

现在,客户端“ A”调用/ connect / token端点以获取access_token

/connect/revocation可以由两个客户端调用。

例如(client_id=B):

[POST]
https://localhost:44367/connect/revocation
[Header]
Content-Type: application/x-www-form-urlencoded
[Request Body]//line break for easy readability purpose only
token=aac0ebb65a999067beda705d478879e915c9f0699582afbcdb5f94fae9210a81
&token_type_hint=access_token
&client_id=B

这将给出200OK响应

现在,如果您调用/connect/userinfo端点,即使从吊销端点获得200OK响应,您仍将能够获得userinfo。

但是,如果您使用client_id作为A调用吊销终结点

例如(client_id=A):

[POST]
https://localhost:44367/connect/revocation
[Header]
Content-Type: application/x-www-form-urlencoded
[Request Body]//line break for easy readability purpose only
token=aac0ebb65a999067beda705d478879e915c9f0699582afbcdb5f94fae9210a81
&token_type_hint=access_token
&client_id=A

这还将给出200OK响应。

如果您在撤销后致电/connect/userinfo。现在,这将给出unauthorized的响应。似乎正确。

我不知道此设计选择是否是故意的,还是IdentityServer4中的错误