【发布时间】:2020-02-17 22:51:36
【问题描述】:
为什么在使用Microsoft.AspNetCore.Authentication.OpenIdConnect 中间件时,带有过期 access_token 的表单 POST 会导致 GET?发生这种情况时,输入到表单中的任何数据都会丢失,因为它没有到达 HttpPost 端点。相反,在 signin-oidc 重定向之后,请求将通过 GET 重定向到相同的 URI。这是一个限制,还是我的某些配置不正确?
我在缩短 AccessTokenLifetime 后注意到了这个问题,目的是强制更频繁地更新用户的声明(即,如果用户被禁用或他们的声明被撤销)。我只在 OpenIdConnect 中间件的 OpenIdConnectionOptions 设置为 true options.UseTokenLifetime = true; 时复制了此内容(将其设置为 false 会导致经过身份验证的用户的声明未按预期更新)。
我能够使用 IdentityServer4 示例快速入门 5_HybridFlowAuthenticationWithApiAccess 重新创建并演示此行为,并进行了以下更改。基本上,有一个具有 HttpGet 和 HttpPost 方法的授权表单。如果您等待的时间超过了 AccessTokenLifetime(在本例中配置为仅 30 秒)提交表单,则会调用 HttpGet 方法而不是 HttpPost 方法。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
// the following was added
options.SlidingExpiration = false;
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("api1");
options.ClaimActions.MapJsonKey("website", "website");
// the following were changed
options.UseTokenLifetime = true;
options.Scope.Add("offline_access");
});
}
修改IdentityServer/Config.cs中的客户列表
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1",
IdentityServerConstants.StandardScopes.OfflineAccess,
},
AllowOfflineAccess = true,
// the following properties were configured:
AbsoluteRefreshTokenLifetime = 14*60*60,
AccessTokenLifetime = 30,
IdentityTokenLifetime = 15,
AuthorizationCodeLifetime = 15,
SlidingRefreshTokenLifetime = 60,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
UpdateAccessTokenClaimsOnRefresh = true,
RequireConsent = false,
}
添加到MvcClient/Controllers/HomeController
[Authorize]
[HttpGet]
[Route("home/test", Name = "TestRouteGet")]
public async Task<IActionResult> Test()
{
TestViewModel viewModel = new TestViewModel
{
Message = "GET at " + DateTime.Now,
TestData = DateTime.Now.ToString(),
AccessToken = await this.HttpContext.GetTokenAsync("access_token"),
RefreshToken = await this.HttpContext.GetTokenAsync("refresh_token"),
};
return View("Test", viewModel);
}
[Authorize]
[HttpPost]
[Route("home/test", Name = "TestRoutePost")]
public async Task<IActionResult> Test(TestViewModel viewModel)
{
viewModel.Message = "POST at " + DateTime.Now;
viewModel.AccessToken = await this.HttpContext.GetTokenAsync("access_token");
viewModel.RefreshToken = await this.HttpContext.GetTokenAsync("refresh_token");
return View("Test", viewModel);
}
【问题讨论】:
标签: asp.net-core identityserver4 openid-connect