环境:
- IdentityServer4支持隐式流的实例
- 使用 oidc-client-js 的 Angular 7 客户端应用程序
- 使用 IdentityServer3 Katana Access Token Validation Middleware 的 ASP.NET Framework Web API 资源
基本 token 发行和验证在我们的环境中运行良好。我现在正在尝试启用静默刷新技术(如 documented here )。在启用 automaticSilentRenew
和一个简短的 AccessTokenLifetime
之后,我可以在我的浏览器控制台中看到静默请求,正如我所期望的那样。
我可以看到对 IS4 的 UserInfo 端点的两次后续调用(请参见下面的屏幕截图)。第一个是 CORS 预检 OPTIONS
请求。在我的 IProfileService.IsActiveAsync()
自定义实现的断点处,我可以看到此请求已成功通过身份验证(通过检查 httpContext
)。
public class ProfileService : IProfileService
{
private readonly HttpContext _httpContext;
public ProfileService(IHttpContextAccessor httpContextAccessor)
{
_httpContext = httpContextAccessor.HttpContext;
}
...
public async Task IsActiveAsync(IsActiveContext context)
{
var temp = _httpContext.User; // breakpoint here
// call external API with _httpContext.User info to get isActive
}
}
但是,对 UserInfo 端点的第二个请求 (GET
) 未进行身份验证。我在 IProfileService.IsActiveAsync()
中的断点显示没有经过身份验证的用户,因此我验证用户是否处于事件状态(调用另一个 API)的例程返回 false,它被转换为 401。我可以看到这个失败的 GET
请求的 header WWW-Authenticate: error="invalid_token"
。
我已尝试根据 this 指定小于 AccessTokenLifetime
的 IdentityTokenLifetime
没有成功。
这是两个请求的日志:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 OPTIONS http://localhost:5000/connect/userinfo
Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: CORS policy execution successful.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 8.5635ms 204
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5000/connect/userinfo
Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: CORS policy execution successful.
Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: CORS policy execution successful.
IdentityServer4.Hosting.IdentityServerMiddleware:Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.UserInfoEndpoint for /connect/userinfo
IdentityServer4.Validation.TokenValidator:Error: User marked as not active: f84db3aa-57b8-48e4-9b59-6deee3d288ad
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 94.7189ms 401
问题:
如何在静默刷新期间获取对 UserInfo 端点的 GET
请求,以对 HttpContext
进行身份验证?
更新:
添加两个请求的所有 header 的屏幕截图和生成的浏览器 cookie 以调查@Anders 的答案。
最佳答案
好吧,我想我知道发生了什么。您发出静默刷新 token 请求(从我从重定向到 oidc-silent-refresh.html 中看到的内容成功)并且调用第一个 ProfileService 的“IsActiveAsync”(因为它需要通过配置文件服务来生成 token 静默刷新)。您能够看到“HttpContext.User”,因为打开了一个允许发送所有必要 cookie 的 iframe。
用户信息预检请求甚至没有到达配置文件服务,正如您从日志中看到的那样,仅显示一次“调用 IdentityServer 端点:IdentityServer4.Endpoints.UserInfoEndpoint for/connect/userinfo”。此外,UserInfoEndpoint 会阻止任何选项请求通过(您可以在“ProcessAsync”方法的开头验证它是否为真 here)。
现在,当您发出实际的用户信息请求时,您正试图从 HttpContext 获取信息(通常使用来自 cookie 的信息填充),但它是不可访问的,因为请求中没有发送 cookie。提出要求here在“getJson”方法(来自 oidc-client-js 库)中,您可以看到请求中没有发送任何 cookie(如果是,“withCredentials”属性将在请求中设置为 true)。
那么我们如何获取用户的必要信息呢?要获取此信息,我们可以引用“context” ' 传递到 ProfileService 的“IsActiveAsync”,其中包含由访问 token 声明填充的主体(此过程可以在“ValidateAccessTokenAsync”方法中看到 here)。
关于c# - 静默刷新在 OPTIONS 预检上进行身份验证,但不在 GET 到 UserInfo 端点上进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54775582/