Должна ли конечная точка connect / userinfo работать после отзыва токена? - PullRequest
0 голосов
/ 14 мая 2019

Я использую IdentityServer4 для входа в систему на основе токена

После входа пользователя я получаю access_token и refresh_token

Когда пользователь пытается выйти из системы, я звоню/connect/revocation конечная точка IdentityServer4

Но даже после отзыва токена, когда я вызываю конечную точку /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 голосов
/ 14 мая 2019

Несколько замечаний:

  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 от конечной точки отзыва.

Однако, если вы вызываете конечную точку отзыва с 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

...