【问题标题】:ASP.NET Core 3.1 OpenIDConnect, how to update claims without user logging outASP.NET Core 3.1 OpenIDConnect,如何在不注销用户的情况下更新声明
【发布时间】:2021-06-22 04:24:15
【问题描述】:

使用ASP.NET Core 3.1OpenIDConnect,我能够进行身份验证,并且在流程中,我添加了用户声明,例如授予资源访问权限的用户角色。

如果我在运行时更改用户“角色”,我不希望用户退出,而是希望强制刷新令牌,并拥有新的声明/角色。

目前我正在使用这个options.Events.OnTokenValidated = async context => { /* add claims if authenticated */} 最初添加声明。

我添加了中间件来检测用户是否有新的“角色”,并希望强制事件再次触发。

处理这个问题的正确方法是什么?

【问题讨论】:

    标签: asp.net-core openid-connect


    【解决方案1】:

    您可以在每次刷新访问令牌时更新它的内容,并且可以通过将 UpdateAccessTokenClaimsOnRefresh 标志设置为 true 来启用它。请参阅文档here

    问题是在数据库更改和访问令牌刷新之间您可以接受多少“滞后”。

    如果您想在客户端更新用户,那么您必须使用 AddCookie 处理程序中的事件之一。 AddOpenIDConnect 处理程序仅在用户最初登录时参与。之后,AddCookie 负责并拥有用户对象(ClaimsPrincipal)。

    【讨论】:

      【解决方案2】:

      我有两种解决方案,都不太理想。

      当您使用 Ajax 调用时,第一个不起作用。 (我遇到了 CORS 错误,发现无法允许主机;预检调用失败。)

      // middleware
      public async Task Invoke(HttpContext context) {
          
          if (userRolesHaveChanged) {
      
              context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme,
                         new AuthenticationProperties { RedirectUri = redirectUrl });
              return;
          }
      
          // the normal flow
          await next(context);
      }
      

      访问 XMLHttpRequest 在 'https://login.microsoftonline.com/XYZ/oauth2/v2.0/authorize?client_id=xyz&redirect_uri=https%3A%2F%2Flocalhost%3A8083%2FAuth%2FLogin%2FSignInOidc&response_type=id_token&/x-client-SKU=ID_NETSTANDARD2_0&x -客户端版本=5.5.0.0' (重定向自“https://localhost:8083/PATH”)来自原点 “https://localhost:8083”已被 CORS 策略阻止:响应 预检请求未通过访问控制检查:否 'Access-Control-Allow-Origin' 标头出现在请求的 资源。

      为了克服 CORS 问题,我提出了一个 HACK,通过使用 Cookie 过期时间。

      首先配置 OpenIdConnect 使用 cookie 过期时间, 然后当用户角色发生变化时,只需删除控制 cookie。

      // startup
      services.Configure<OpenIdConnectOptions> (OpenIdConnectDefaults.AuthenticationScheme, options =>
      
                      options.UseTokenLifetime = false; // Expire time
                      options.SignInScheme = "hack";
      
                      // SNIPPED CODE 
      
      
      .AddCookie("hack", "hack", options =>
                      {
                          const int minute = 60;
                          const int hour = minute * 60;
                          const int day = hour * 24;
                          options.ExpireTimeSpan = TimeSpan.FromSeconds(day/2.0);
                      })
      

      然后在中间件内

      // middleware
      public async Task Invoke(HttpContext context) {
              
              if (userRolesHaveChanged) {    
      
                    // force expire....
                    // causes the next page load to indirectly call ChallengeAsync
                    context.Response.Cookies.Delete(".AspNetCore.hack");
      
                    // also possibly set some other controlling variable,
                    // and deal with it, within the Ajax call
                    // e.g.
                    context.Response.Cookies.Append("autoSignIn", redirectUrl, 
                             new CookieOptions { HttpOnly = false });
              }
      

      解决方案既糟糕又笨拙。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-14
        • 2022-06-13
        • 2014-01-05
        • 2013-10-28
        • 1970-01-01
        • 2019-12-24
        • 2015-10-14
        • 2020-11-12
        相关资源
        最近更新 更多