IdentiyServer4 - проверка API, если срок действия токена истек - PullRequest
0 голосов
/ 31 декабря 2018

Во время некоторого тестирования с IdentityServer4 я обнаружил «странное» поведение.

Мой API не обнаруживает токены с истекшим сроком действия.

Настройка:

  • Проект MVC, на котором размещен IdentiyServer4
  • Проект API с одной конечной точкой теста
  • Клиент cmd

На стороне IdentiyServer4 AccessTokenLifetime для моего клиента cmdустановлено на 20 секунд.

При регистрации в моем клиенте я вижу, что значение exp токена JWT правильно установлено на now + 20 секунд.

API принимаетвсе звонки от клиента с токеном (включая токены с истекшим сроком действия).

Я ожидаю, что мой API будет принимать только действительные / еще не истекшие токены.Но это не так.Нужно ли включать / добавлять какой-либо компонент проверки в моем проекте API?

Вот конфигурация API:

public class Startup
{
    public void Configure( IApplicationBuilder app, IHostingEnvironment env )
    {
        if ( env.IsDevelopment() )
            app.UseDeveloperExceptionPage();

        app.UseAuthentication();
        app.UseMvc();
    }

    public void ConfigureServices( IServiceCollection services )
    {
        services.AddMvc();
        services.AddAuthorization();
        services
            .AddAuthentication( IdentityServerAuthenticationDefaults.AuthenticationScheme )
            .AddIdentityServerAuthentication( options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;
                options.ApiName = "ApiPoc";
            } );
    }
}

Конфигурация IdentityServer-Host:

public class Startup
{
    public void Configure( IApplicationBuilder app, IHostingEnvironment env )
    {
        if ( env.IsDevelopment() )
            app.UseDeveloperExceptionPage();

        app.UseIdentityServer();
    }

    public void ConfigureServices( IServiceCollection services )
    {
        // IdentityServer 4
        services
            .AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryIdentityResources( Config.GetIdentityResources() ) //check below
            .AddInMemoryApiResources( Config.GetApiResources() )
            .AddInMemoryClients( Config.GetClients() )
            .AddProfileService<ProfileService>();

        // Test - custom user repo
        services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
        services.AddTransient<IProfileService, ProfileService>();
    }
}

public class Config
{
    public static IEnumerable<ApiResource> GetApiResources() =>
        new List<ApiResource>
        {
            new ApiResource( "ApiPoc", "API PoC" )
        };

    public static IEnumerable<Client> GetClients() => 
        new List<Client>
        {
            new Client
            {
                ClientId = "CmdClient",
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                ClientSecrets =
                {
                    new Secret( "CmdClientSecret".Sha256() )
                },
                AllowedScopes = { "ApiPoc" },
                AccessTokenLifetime = 20,
                AccessTokenType = AccessTokenType.Jwt,
                SlidingRefreshTokenLifetime = 1296000
            }
        };

    public static IEnumerable<IdentityResource> GetIdentityResources() => 
        new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile()
        };
}

Код клиента Cmd:

private static async Task DoRequestInLoop()
{
    var client = new HttpClient();
    var disco = await client.GetDiscoveryDocumentAsync( "http://localhost:5000" ).ConfigureAwait( false );
    if ( disco.IsError )
    {
        Console.WriteLine( $"Failed to get discovery document: {disco.Error}" );
        return;
    }

    var tokenResponse = await client.RequestPasswordTokenAsync( new PasswordTokenRequest
                                                                {
                                                                    Address = disco.TokenEndpoint,
                                                                    ClientId = "CmdClient",
                                                                    ClientSecret = "CmdClientSecret",
                                                                    Scope = "ApiPoc",
                                                                    Password = "user",
                                                                    UserName = "password",
                                                                    Parameters = new Dictionary<String, String>
                                                                    {
                                                                        { "UserGroup", "A_Admin" },
                                                                        { "Tenant", "A" }
                                                                    }
                                                                },
                                                                CancellationToken.None ).ConfigureAwait( false );
    if ( tokenResponse.IsError )
    {
        Console.WriteLine( $"Failed to obtain token: {tokenResponse.Error}." );
        return;
    }

    var json = tokenResponse.Json.ToString();
    client.SetBearerToken( tokenResponse.AccessToken );
    Console.WriteLine( $"Token: {json}" );

    while ( !_loopCanceled )
    {
        var response = await client.GetAsync( "http://localhost:5001/api/Values" ).ConfigureAwait( false );
        Console.WriteLine( !response.IsSuccessStatusCode ? $"Request failed with status code {response.StatusCode}" : "Request successful." );
        await Task.Delay( 22000 ).ConfigureAwait( false );
    }
}

Токен, полученный клиентом от IdentityServer (вы можете видеть, что он действителен только в течение 20 секунд, что правильно)

{
  "nbf": 1546243372,
  "exp": 1546243392,
  "iss": "http://localhost:5000",
  "aud": [
    "http://localhost:5000/resources",
    "ApiPoc"
  ],
  "client_id": "CmdClient",
  "sub": "1",
  "auth_time": 1546243372,
  "idp": "local",
  "SomeClaim": "Claim",
  "scope": [
    "ApiPoc"
  ],
  "amr": [
    "custom"
  ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...