IdentiyServer4 – API检查令牌是否已过期

时间:2018-12-31 08:16:48

标签: c# asp.net-core identityserver4

在使用IdentityServer4进行测试时,我发现了一种“奇怪”的行为。

我的API无法检测到过期的令牌。

设置:

  • 托管IdentiyServer4的MVC项目
  • 具有单个测试端点的API项目
  • cmd客户端

在IdentiyServer4端,我的cmd客户端的AccessTokenLifetime设置为20秒。

签入客户端时,我可以看到JWT令牌的exp值已正确设置为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-主机配置:

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"
  ]
}

0 个答案:

没有答案