继续与 OIDC JS 客户端和身份服务器进行会话 4 授权流与 Azure 应用服务上的 PKCE 流

Posted

技术标签:

【中文标题】继续与 OIDC JS 客户端和身份服务器进行会话 4 授权流与 Azure 应用服务上的 PKCE 流【英文标题】:Keep getting session out with OIDC JS client and Identity server 4 Authorization flow with PKCE flow on Azure app services 【发布时间】:2021-04-16 12:53:49 【问题描述】:

在应用程序每 10 秒重新加载一次时,使用带有 OIDC JS 客户端的 Identity server 4,在我可以看到的网络选项卡中

结束会话 URL 总是被取消并且应用程序频繁重新加载

Request URL: https://falconidentityserver.azurewebsites.net/connect/endsession?id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjU1RDY5MTZFODVCOUNENTgwRjQ0RTMzNzREMjZFOUFCIiwidHlwIjoiSldUIn0.eyJuYmYiOjE2MTAzNzU0NjQsImV4cCI6MTYxMDM3NTc2NCwiaXNzIjoiaHR0cHM6Ly9mYWxjb25pZGVudGl0eXNlcnZlci5henVyZXdlYnNpdGVzLm5ldCIsImF1ZCI6IkZldGVfQmlyZF9VSSIsImlhdCI6MTYxMDM3NTQ2NCwiYXRfaGFzaCI6IlVDaUt3LXBBdi14aFVINFRZVXk1a1EiLCJzX2hhc2giOiI5clc3UUY5ZEtqRXdubE9lTWpRTTVBIiwic2lkIjoiQjYwNEJBNEU5MTEyOURCQjYzNTJFOEJDNDZFQUM5QkUiLCJzdWIiOiJlNDEzMTIwYS0yYWEzLTQzZTktYTQ1MC1lZWU2NzBjY2EzMjEiLCJhdXRoX3RpbWUiOjE2MTAzNzU0NTEsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.lmfq1ZJ2ukkrZ-FPjtCPaEsBYM0HXCAF496dNGMH0WP-SBFbbSllLSPGcavpruzzA0n-JQmkshtEqhyMvk5-c81dQLgjblrQ-X5QrzGoRd6fXDMnWwR0dlm2ZC2TcPOcBJXdaW1nfjLChxxrQljHMNLBr1tAmPfTfx0kaG7uvoXg1iY1aNmBsFUs4erdYs24Wd0JPtGzlHrGc3wyXk7aJNS77Ocu9SHUTL5XLsecOPMX0CVqeAX0ibRT6b-VuJ6u0egMKzR6yS8vCx4DNdHIScuX-zyMvisDePiCwqbN_K9VE0iwy2CmNfMKmioPX-aora7V1qZwCdj2-Lp-OSVVwg

身份服务器客户端设置

new Client
                
                    ClientId = "XXXXXXXXXXXXXX",
                    ClientName = "XXXXXXXXXXXXXXXX",
                    AllowedCorsOrigins = CorsUris(configuration),
                    AllowedGrantTypes = GrantTypes.Code,
                    AllowAccessTokensViaBrowser = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowAccessTokensViaBrowser").Value),
                    IdentityTokenLifetime = 300,
                    AccessTokenLifetime = 200,
                    RequireConsent = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireConsent").Value),
                    UpdateAccessTokenClaimsOnRefresh = bool.Parse(configuration.GetSection("IdentityServer:Client:UpdateAccessTokenClaimsOnRefresh").Value),
                    RedirectUris = LocalRedirectUris(configuration),
                    PostLogoutRedirectUris = LocalRedirectUris(configuration),
                    AllowedScopes = AllowedScopes(),
                    AllowOfflineAccess = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowOfflineAccess").Value),
                    AccessTokenType = AccessTokenType.Jwt,
                    RequireClientSecret = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireClientSecret").Value),
                    RequirePkce = bool.Parse(configuration.GetSection("IdentityServer:Client:RequirePkce").Value),
                    //AllowRememberConsent = true
                ,

OIDC 客户端设置

openID = 
authority: 'https://falconidentityserver.azurewebsites.net',
client_id: 'xxxxxxxx',
redirect_uri: 'https://localhost:4200/auth-callback',
silent_redirect_uri: 'https://localhost:4200/assets/silent-renew.html',
response_type: 'code',
scope: 'openid profile email',
automaticSilentRenew: true

;

我不知道我缺少什么以及问题出在哪里。谁能帮我解决这个问题

我正在执行静默更新,您可以在网络选项卡中看到它运行良好。

OIDC 用户管理器日志

【问题讨论】:

错误提示“不安全的请求”。您的一些 URL 是 HTTPS(安全),而另一些是 HTTP(不安全)。 是的,因为我在本地主机上使用 SSL 运行 Angular 应用程序,而身份服务器托管在 Azure 上 但是你正在重定向!!! 对不起,我正在运行没有 SSL 的 Angular 应用程序,是的,它保持重定向 那为什么权限是https呢? 【参考方案1】:

我的问题是

单点注销 (monitorSession: true) 这是做什么的? -- 登录到您的应用程序后(从 IDP 服务器发布重定向后,OIDC-Client JS 将在 iframe 中包含 CheckSession 端点,并且 OIDC 库每 2 秒(默认)在内部 ping 此 iframe 以验证 idsrv.session cookie 值是否匹配使用应用程序 id 令牌中的值,如果它们不匹配,OIDC 将引发用户注销事件 addUserSignedOut。这取决于您的应用程序,当这甚至从 OIDC 引发时您要如何处理。仅仅因为您启用了单点登录out,除非应用程序处理,否则不会将用户带回登录页面

从以下来源挖掘更多内容后

https://github.com/IdentityModel/oidc-client-js/issues/729

https://github.com/IdentityServer/IdentityServer4/issues/1983

我需要添加

builder.Services.ConfigureApplicationCookie(options =>
            
                // we need to disable to allow iframe for authorize requests
                options.Cookie.SameSite = SameSiteMode.None;
            );

现在该应用程序在 CHROME 中运行良好,但在 SAFARI 中却不行。

我需要管理 ASP.NET 和 ASP.NET Core 中即将发生的 SameSite Cookie 更改

https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/

https://docs.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1#supporting-older-browsers

https://www.identityserver.com/documentation/saml2p/config-sp/samesitecookies/

https://www.thinktecture.com/en/identity/samesite/prepare-your-identityserver/

添加下面的类

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
 
namespace Microsoft.Extensions.DependencyInjection

   public static class SameSiteCookiesServiceCollectionExtensions
   
      /// <summary>
      /// -1 defines the unspecified value, which tells ASPNET Core to NOT
      /// send the SameSite attribute. With ASPNET Core 3.1 the
      /// <seealso cref="SameSiteMode" /> enum will have a definition for
      /// Unspecified.
      /// </summary>
      private const SameSiteMode Unspecified = (SameSiteMode) (-1);
 
      /// <summary>
      /// Configures a cookie policy to properly set the SameSite attribute
      /// for Browsers that handle unknown values as Strict. Ensure that you
      /// add the <seealso cref="Microsoft.AspNetCore.CookiePolicy.CookiePolicyMiddleware" />
      /// into the pipeline before sending any cookies!
      /// </summary>
      /// <remarks>
      /// Minimum ASPNET Core Version required for this code:
      ///   - 2.1.14
      ///   - 2.2.8
      ///   - 3.0.1
      ///   - 3.1.0-preview1
      /// Starting with version 80 of Chrome (to be released in February 2020)
      /// cookies with NO SameSite attribute are treated as SameSite=Lax.
      /// In order to always get the cookies send they need to be set to
      /// SameSite=None. But since the current standard only defines Lax and
      /// Strict as valid values there are some browsers that treat invalid
      /// values as SameSite=Strict. We therefore need to check the browser
      /// and either send SameSite=None or prevent the sending of SameSite=None.
      /// Relevant links:
      /// - https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1
      /// - https://tools.ietf.org/html/draft-west-cookie-incrementalism-00
      /// - https://www.chromium.org/updates/same-site
      /// - https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
      /// - https://bugs.webkit.org/show_bug.cgi?id=198181
      /// </remarks>
      /// <param name="services">The service collection to register <see cref="CookiePolicyOptions" /> into.</param>
      /// <returns>The modified <see cref="IServiceCollection" />.</returns>
      public static IServiceCollection ConfigureNonBreakingSameSiteCookies(this IServiceCollection services)
      
         services.Configure<CookiePolicyOptions>(options =>
         
            options.MinimumSameSitePolicy = Unspecified;
            options.OnAppendCookie = cookieContext =>
               CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            options.OnDeleteCookie = cookieContext =>
               CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
         );
 
         return services;
      

      private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
      
         if (options.SameSite == SameSiteMode.None)
         
            var userAgent = httpContext.Request.Headers["User-Agent"].ToString();

            if (DisallowsSameSiteNone(userAgent))
            
               options.SameSite = Unspecified;
            
         
      
 
      /// <summary>
      /// Checks if the UserAgent is known to interpret an unknown value as Strict.
      /// For those the <see cref="CookieOptions.SameSite" /> property should be
      /// set to <see cref="Unspecified" />.
      /// </summary>
      /// <remarks>
      /// This code is taken from Microsoft:
      /// https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
      /// </remarks>
      /// <param name="userAgent">The user agent string to check.</param>
      /// <returns>Whether the specified user agent (browser) accepts SameSite=None or not.</returns>
      private static bool DisallowsSameSiteNone(string userAgent)
      
         // Cover all ios based browsers here. This includes:
         //   - Safari on iOS 12 for iPhone, iPod Touch, iPad
         //   - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
         //   - Chrome on iOS 12 for iPhone, iPod Touch, iPad
         // All of which are broken by SameSite=None, because they use the
         // iOS networking stack.
         // Notes from Thinktecture:
         // Regarding https://caniuse.com/#search=samesite iOS versions lower
         // than 12 are not supporting SameSite at all. Starting with version 13
         // unknown values are NOT treated as strict anymore. Therefore we only
         // need to check version 12.
         if (userAgent.Contains("CPU iPhone OS 12")
            || userAgent.Contains("iPad; CPU OS 12"))
         
            return true;
         

         // Cover Mac OS X based browsers that use the Mac OS networking stack.
         // This includes:
         //   - Safari on Mac OS X.
         // This does not include:
         //   - Chrome on Mac OS X
         // because they do not use the Mac OS networking stack.
         // Notes from Thinktecture: 
         // Regarding https://caniuse.com/#search=samesite MacOS X versions lower
         // than 10.14 are not supporting SameSite at all. Starting with version
         // 10.15 unknown values are NOT treated as strict anymore. Therefore we
         // only need to check version 10.14.
         if (userAgent.Contains("Safari")
            && userAgent.Contains("Macintosh; Intel Mac OS X 10_14")
            && userAgent.Contains("Version/"))
         
            return true;
         

         // Cover Chrome 50-69, because some versions are broken by SameSite=None
         // and none in this range require it.
         // Note: this covers some pre-Chromium Edge versions,
         // but pre-Chromium Edge does not require SameSite=None.
         // Notes from Thinktecture:
         // We can not validate this assumption, but we trust Microsofts
         // evaluation. And overall not sending a SameSite value equals to the same
         // behavior as SameSite=None for these old versions anyways.
         if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
         
            return true;
         

         return false;
      
   

配置和启用cookies

public void ConfigureServices(IServiceCollection services)

   // Add this
   services.ConfigureNonBreakingSameSiteCookies();

 
public void Configure(IApplicationBuilder app)

   // Add this before any other middleware that might write cookies
   app.UseCookiePolicy();

   // This will write cookies, so make sure it's after the cookie policy
   app.UseAuthentication();

完成所有更改后,我仍然面临 SAFARI

的问题

【讨论】:

第二个链接显示 UserAgent 并且可能需要设置/修改用户代理。也可能是代码在 Windows 上运行,而不是在 Apple 机器上运行。 Apple 操作系统和/或内核可能需要更新。 问题是我已将身份服务器托管到远程并从本地使用它。所以域不同,这就是cookie无效的原因。但不太确定如何修复 safari 您的苹果机器上需要一个 Windows 凭据。请参阅:answers.uillinois.edu/illinois/page.php?id=68546 这与我的问题完全无关 你登录了吗?用于登录的凭据是什么?要进入域,您需要登录。

以上是关于继续与 OIDC JS 客户端和身份服务器进行会话 4 授权流与 Azure 应用服务上的 PKCE 流的主要内容,如果未能解决你的问题,请参考以下文章

身份服务器 3 用户会话生命周期

Oidc 客户端 js:静默访问令牌更新中断,因为身份服务器身份验证 cookie 滑动到期不起作用

没有用户使用身份服务器和javascript的oidc客户端登录SilentCallback

Oidc 客户端 js,不要在客户端使用 Date.now

使用带有身份服务器 4 的 oidc 客户端进行静默登录

使用 Steam OpenId 登录(oidc-client-js)