断言不在 AspNetCore 身份验证 OpenIdConnect 的有效时间范围内

Assertion is not within its valid time range in AspNetCore Authentication OpenIdConnect

我在尝试为另一个应用程序获取令牌时开始收到此错误。

Additional information: AADSTS70002: Error validating credentials. AADSTS50013: Assertion is not within its valid time range.

这是在我从 AspNetCore 的 1.0.1 升级到 1.1.0 后开始出现的。如果我清除我的 cookie,这个错误就会消失一段时间。

下面是我用来获取此令牌的代码。它主要改编自 GitHub.

上示例中的代码
var userObjectId = (user.FindFirst(AuthSettings.UserObjectIdClaimName))?.Value;
AuthenticationResult authResult = null;
var authContext = GetAuthContext(userObjectId);
ClientCredential credential = new ClientCredential(AuthSettings.ClientId, AuthSettings.ClientSecret);
var claimsIdentity = user.Identity as ClaimsIdentity;

var token = claimsIdentity?.BootstrapContext as string;
if (token != null)
{
    try
    {
        authResult = await authContext.AcquireTokenAsync(appId, credential,
            new UserAssertion(token)); // Error here
    }
    catch (Exception) { }

}
if (authResult == null)
{
    // Error no token in cache here
    authResult = await authContext.AcquireTokenSilentAsync(appId, credential,
        new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
}


return authResult.AccessToken;

你知道有趣的是 AcquireTokenSilentAsync 如果第一次尝试失败就永远不会起作用,因为令牌缓存是空的。在我的 Startup 中,我在 OnAuthorizationCodeReceived 中有代码继续执行并将令牌存储在令牌缓存中。此回调 从未 执行。据推测,如果第一批代码不起作用,那么如果这段代码起作用,回退将处理它。

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    ClientId = authSettings.ClientId,
    Authority = authSettings.Authority,
    ResponseType = OpenIdConnectResponseType.IdToken,
    PostLogoutRedirectUri = authSettings.PostLogoutUrl,
    TokenValidationParameters = new TokenValidationParameters()
    {
        SaveSigninToken = true
    },
    Events = new OpenIdConnectEvents
    {
        OnRemoteFailure = authHelper.CreateOnRemoteFailureRedirectHandler("/Home/Error"),
        OnAuthorizationCodeReceived =
            authHelper.CreateOnAuthorizationCodeRecievedAcquireAdditionalTokenHandler(new[] { CustomerManagerApi })
    },
});

这是 OnAuthorizationCodeRecieved 当前未执行的代码:

var userObjectId = (context.Ticket?.Principal?.FindFirst(AuthSettings.UserObjectIdClaimName))?.Value;
var clientCred = new ClientCredential(AuthSettings.ClientId, AuthSettings.ClientSecret);
var authContext = new AuthenticationContext(AuthSettings.Authority, TokenCacheCreator(userObjectId));
var redirectAddressForAuthCode = new Uri(context.Properties.Items[OpenIdConnectDefaults.RedirectUriForCodePropertiesKey]);
authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, redirectAddressForAuthCode, clientCred, applicationId);

context.HandleCodeRedemption();

未触发 OnAuthorizationCodeReceived 的原因是您将 ResponseType 设置为 OpenIdConnectResponseType.IdToken,这不会向客户端发送授权码。

Additional information: AADSTS70002: Error validating credentials. AADSTS50013: Assertion is not within its valid time range.

对于此错误,请确保访问令牌未过期,然后再发送使用它进行用户断言的令牌请求。

我在交换用户断言以获取 Microsoft Graph API scope Token 时遇到了同样的问题,我发现 .Net Core Web API 允许过期令牌在过期后再保留 5 分钟,由于默认 5 分钟令牌验证时钟偏差 属性。

所以我将 TokenValidationParameters 的 ClockSkew 属性 设置为 TimeSpan.Zero,这阻止了过期的令牌请求,也解决了断言有效时间范围问题。