【问题标题】:IdentityServer4: auth_time is missingIdentityServer4:auth_time 丢失
【发布时间】:2019-09-30 12:39:50
【问题描述】:

我有一个使用 identityserver4 服务器进行身份验证的 Angular(asp.net 核心)应用程序。

登录时一切正常,显示登录表单并返回 id_token 和 access_token。

但是,一小时后,当 spa 应用程序再次尝试登录时(生命周期为 3600 秒 = 1 小时),我收到内部服务器错误 500:身份服务器4 上的 “auth_time is missing”侧面

我发现恢复状态的唯一方法是访问 identityserver4 网站并注销。

完整的错误是:

System.InvalidOperationException: auth_time is missing.
   at IdentityServer4.Extensions.PrincipalExtensions.GetAuthenticationTimeEpoch(IIdentity identity)
   at IdentityServer4.Services.DefaultClaimsService.GetStandardSubjectClaims(ClaimsPrincipal subject)
   at IdentityServer4.Services.DefaultClaimsService.GetAccessTokenClaimsAsync(ClaimsPrincipal subject, Resources resources, ValidatedRequest request)
   at IdentityServer4.Services.DefaultTokenService.CreateAccessTokenAsync(TokenCreationRequest request)
   at IdentityServer4.ResponseHandling.AuthorizeResponseGenerator.CreateImplicitFlowResponseAsync(ValidatedAuthorizeRequest request, String authorizationCode)
   at IdentityServer4.ResponseHandling.AuthorizeResponseGenerator.CreateResponseAsync(ValidatedAuthorizeRequest request)
   at IdentityServer4.Endpoints.AuthorizeEndpointBase.ProcessAuthorizeRequestAsync(NameValueCollection parameters, ClaimsPrincipal user, ConsentResponse consent)
   at IdentityServer4.Endpoints.AuthorizeEndpoint.ProcessAsync(HttpContext context)
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)
   at IdentityServer4.Hosting.MutualTlsTokenEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

关于配置的一些数据:

identityserver4上的客户端配置如下:

new Client
{
    ClientId = "site.spa",
    ClientName = "SPA Client",
    AllowedGrantTypes = GrantTypes.Implicit,
    AllowAccessTokensViaBrowser = true,
    IdentityTokenLifetime = 3600,
    AccessTokenLifetime = 3600,
    RedirectUris = { "http://mywebsitespa.azurewebsites.net/signin-oidc" },
    PostLogoutRedirectUris = { "http://mywebsitespa.azurewebsites.net/signout-callback-oidc" },
    AllowedCorsOrigins = { "http://mywebsitespa.azurewebsites.net" },
    AllowedScopes = new List<string>
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        JwtClaimTypes.AuthenticationTime,
        "api1"
    },
    AlwaysIncludeUserClaimsInIdToken = true,
    RequireConsent = false,
},

第一次登录时的 Jwt 令牌(已解密)显示以下信息:

{
  "nbf": 1557750961,
  "exp": 1557751261,
  "iss": "http://mywebsite.azurewebsites.net",
  "aud": "site.spa",
  "nonce": "N0.92260399539729281557750948716",
  "iat": 1557750961,
  "at_hash": "-ir-JDkxDre1YkrV-Nt5Ag",
  "sid": "58f3f7ed9786043bb5634129dff8882b",
  "sub": "1",
  "auth_time": 1557750961,
  "idp": "local",
  "name": "user",
  "given_name": "user",
  "family_name": "family_name",
  "website": "http://mywebsite.azurewebsites.com",
  "amr": [
    "pwd"
  ]
}

登录剃须刀页面有这个代码:

public async Task OnGetAsync(string returnUrl = null)
{
    if (!string.IsNullOrEmpty(ErrorMessage))
    {
        ModelState.AddModelError(string.Empty, ErrorMessage);
    }

    returnUrl = returnUrl ?? Url.Content("~/");

    // Clear the existing external cookie to ensure a clean login process
    await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

    ReturnUrl = returnUrl;
}

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: true);

        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in. Redirecting to: " + returnUrl);
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

这是 ConfigureServices()

public void ConfigureServices(IServiceCollection services)
{
    IdentityModelEventSource.ShowPII = true;

    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<MyIdentityDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    // Identity Server
    services.AddIdentityServer(options =>
    {
        options.UserInteraction = new IdentityServer4.Configuration.UserInteractionOptions
        {
            LoginUrl = "/Identity/Account/Login",
            LogoutUrl = "/Identity/Account/Logout",
        };
    })
    .AddDeveloperSigningCredential()
    .AddInMemoryApiResources(IS4Config.GetApiResources())
    .AddInMemoryClients(IS4Config.GetClients())
    .AddInMemoryIdentityResources(IS4Config.GetIdentityResources());

    // Identity management
    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddEntityFrameworkStores<MyIdentityDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddAuthentication();

    services.ConfigureApplicationCookie(options =>
    {
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
    });

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    });
}

还有 Configure()

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment() || env.IsStaging())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseIdentityServer();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseAuthentication();

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

知道是什么原因导致 identityserver4 出现此错误吗?

【问题讨论】:

  • 您在 IDS4 端的登录操作上是否进行了自定义操作?
  • @VidmantasBlazevicius 我在问题中添加了登录剃须刀页面的代码。
  • 似乎是 IdentityServer 中带有身份验证 cookie 的东西。您能否列出整个 idsrv 配置,尤其是与 auth-scheme 相关的所有内容?
  • @d_f 我添加了 ConfigureServices() 和 Configure()。这是你的意思吗?
  • 最小的一个是官方模板:github.com/IdentityServer/IdentityServer4.Templates/blob/master/…,但是在你删除上面的东西之后,它看起来和你的很相似。但是您可以尝试完全复制粘贴它。考虑服务注册的顺序。您在 IdSrv 之后注册身份 - 可能它会覆盖 cookie。

标签: angular asp.net-core identityserver4


【解决方案1】:

将 AddAspNetIdentity() 添加到 services.AddIdentityServer() 问题消失了。

// Identity Server configuration
services.AddIdentityServer(options =>
{
    options.Events.RaiseErrorEvents = true;
    options.Events.RaiseInformationEvents = true;
    options.Events.RaiseFailureEvents = true;
    options.Events.RaiseSuccessEvents = true;

    options.UserInteraction = new IdentityServer4.Configuration.UserInteractionOptions
    {
        LoginUrl = "/Identity/Account/Login",
        LogoutUrl = "/Identity/Account/Logout",
    };
})
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(IS4Config.GetApiResources())
.AddInMemoryClients(IS4Config.GetClients())
.AddInMemoryIdentityResources(IS4Config.GetIdentityResources())   
.AddAspNetIdentity<IdentityUser>();

【讨论】:

    猜你喜欢
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    相关资源
    最近更新 更多