阻止过期的访问令牌从资源服务器中检索数据

时间:2018-11-13 16:31:47

标签: asp.net-core-2.0 identityserver4

我一直在摆弄IDS 4,但有一个小问题。我将令牌寿命设置为大约15秒,即使它们已过期,我仍然可以从资源服务器中检索日期。如果我从客户端调用的标头中删除令牌,则会收到401错误。

客户端

    [Authorize]
    public async Task<ActionResult> Shouts()
    {

        var accessToken = await HttpContext.GetTokenAsync("access_token");
        var tokenh = new JwtSecurityTokenHandler();

        var jwtSecurityToken= tokenh.ReadJwtToken(accessToken);

        var val = jwtSecurityToken.ValidTo;



        using (var client = new HttpClient())
        {

            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
            var rawResponse = await client.GetAsync("http://localhost:5002/api/Values/Get");

            if (rawResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized)
            {
                var refreshSucc = await this.RefreshTokensAsync(this.HttpContext);
                if (!refreshSucc)
                {
                    var authServerInfo = await this.GetAuthenticationServerInfo();
                    return Redirect(authServerInfo.AuthorizeEndpoint);
                }
            }

            var response = await (rawResponse).Content.ReadAsStringAsync();
            var data = JsonConvert.DeserializeObject<List<String>>(response);
            return View("Shouts", data);
        }
    }
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            services.AddAuthentication(options =>
            {                
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";                
            })
                .AddCookie("Cookies",o=>o.LogoutPath="/home/logout")
                .AddOpenIdConnect("oidc", opt => 
                {
                    opt.SignInScheme = "Cookies";
                    opt.Authority = "http://localhost:5000";
                    opt.RequireHttpsMetadata = false;
                    opt.ClientId = "AuthTest_Code";
                    opt.ClientSecret = "secret";
                    opt.ResponseType = "id_token code";
                    opt.Scope.Add("TestAPI");
                    opt.Scope.Add("offline_access");
                    opt.Scope.Add("email");
                    opt.GetClaimsFromUserInfoEndpoint = true;
                    opt.SaveTokens = true;                    
                });
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

身份验证服务器

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {              
               new Client
            {
                ClientId = "AuthTest_Code",
                ClientSecrets=new []{new Secret("secret".Sha256()) },
                AllowedGrantTypes = GrantTypes.Hybrid,
                AllowedScopes = new List<string>
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.Email,                        
                    "TestAPI"
                },
                AllowAccessTokensViaBrowser=true,
                AllowOfflineAccess=true,
                RedirectUris = new [] { "http://localhost:5001/signin-oidc" },
                PostLogoutRedirectUris={ "http://localhost:5001/signout-callback-odic"},
                RequireConsent=false,
                AccessTokenLifetime=15,
                AbsoluteRefreshTokenLifetime=15
            }
        };
    }

public class Startup
{
    public IHostingEnvironment Environment { get; }

    public Startup(IHostingEnvironment environment)
    {
        Environment = environment;
    }
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        var isServer = services.AddIdentityServer()                
            .AddSigningCredential(new X509Certificate2(@"C:\OpenSSLCerts\Authenticate.pfx", "Password1"))
            .AddInMemoryApiResources(TestConfig.GetApis())
            .AddInMemoryClients(TestConfig.GetClients())
            .AddInMemoryIdentityResources(TestConfig.GetIdentityResources())
            .AddTestUsers(TestConfig.GetUsers());


        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (Environment.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseIdentityServer();

        app.UseStaticFiles();

        app.UseMvcWithDefaultRoute();
    }
}

资源服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace ResourceAPI
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvcCore()
                .AddAuthorization()
                .AddJsonFormatters();

            services.AddAuthentication("Bearer")                
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;                    
                    options.ApiName = "TestAPI";                    
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseAuthentication();
            app.UseMvc();
        }
    }
}


    [Route("api/[controller]")]
    public class ValuesController:ControllerBase
    {
        [HttpGet]
        [Route("Get")]
        [Authorize]
        public async Task<IActionResult> Get()
        {
            var username = User.Claims.FirstOrDefault(t => t.Type == "email")?.Value;
            return Ok(new string[] { "value1", "value2" });
        }      
    }

访问令牌:     eyJhbGciOiJSUzI1NiIsImtpZCI6IjQ0Q0Q4NjFEQjA0MzdEMUM4NUY2REU0MTIyMkFDOEIwMTE3M0Q2MTAiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJSTTJHSGJCRGZSeUY5dDVCSWlySXNCRnoxaEEifQ.eyJuYmYiOjE1NDIxMjc4OTQsImV4cCI6MTU0MjEyNzkwOSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJUZXN0QVBJIl0sImNsaWVudF9pZCI6IkF1dGhUZXN0X0NvZGUiLCJzdWIiOiIxIiwiYXV0aF90aW1lIjoxNTQyMTI3ODkzLCJpZHAiOiJsb2NhbCIsImVtYWlsIjoiRGF2aWRAQUJldHRlckxpZmUuY28uemEiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiZW1haWwiLCJUZXN0QVBJIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.hNskjZz3IBqPg_5T0xVwYEP5RukcMt3l019PRp74vNBkiEr6FLvBADa_eylhNGA8qDd7SwyDkq6APaKxaNt0YybAChZvFW6pzLlfknVVHM1vuN7PDOX9PNGhFK9kSONBypXo6JqV3epactsmJvhr3FZxBSufUDRyV4j_YY3O8TCjJf_5UORc_3ox9clNdjt-VX-BlcDjVbpBw2P76F3pq2IPPDM139H4qYcyaTzSlEbFd3EdVwO6O85bWM1G8yQ9zQAUk23It29oHxTtwsi5Wg4Zpmt7K7AlvKjKxKoxw_Y32QdBkGY9xU_KXOn4h0WJV3LG-InZc7BveLGHq6ncaQ

2 个答案:

答案 0 :(得分:2)

尝试将Web api(资源服务器)中的options.JwtValidationClockSkew属性设置为零

   services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.JwtValidationClockSkew = TimeSpan.Zero;
            options.Authority = "https://localhost:44323";
            options.RequireHttpsMetadata = false;

            options.ApiName = "api1";
        });

Microsoft JWT验证中间件中存在时钟偏斜。默认情况下设置为5分钟。建议将其保留为默认值(300秒/ 5分钟)。

答案 1 :(得分:1)

这很可能是由于默认的5分钟(如果有内存的话)时钟偏移允许。但是,可以在IDS4和承载令牌中间件中覆盖此设置。