Laden...

Chrome - Werden Websites über Bookmarks gecached?

Erstellt von emuuu vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.259 Views
emuuu Themenstarter:in
286 Beiträge seit 2011
vor 3 Jahren
Chrome - Werden Websites über Bookmarks gecached?

Guten Morgen zusammen,

ich habe gerade ein etwas weirdes Problem:
Habe meinen IdentityServer vom Hybrid-Flow auf Code-Flow mit PKCE umgestellt. Es funktioniert auch alles soweit.

Allerdings haben einige (wenige) User das Problem, dass wenn Sie die Website über ein Bookmark aufrufen der IdentityServer denen eine invalid request um die Ohren haut (logs sagen code_challenge is missing).

Mein Problem ist, dass ich den Fehler in keiner Weise reproduzieren kann.

Browserdaten löschen hat nichts gebracht, gelöst werden konnte es bisher nur wenn die Website über Eingeben der Domain in der Adresszeile aufgerufen wird. Danach funktionieren auch die Bookmarks wieder (nur eigene Bookmarks nicht Chromes recently used bookmarks)

Habt ihr irgendeine Idee woran das liegen kann?

Beste Grüße
emuuu

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 3 Jahren

Wenn das so wäre solltest Du das relativ einfach über die Chrome Developer Tools oder Fiddler erkennen können.

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 3 Jahren

Die Schwierigkeit die ich dabei habe ist, dass ich aktuell keinen Zugriff auf eine betroffene Umgebung habe.
Bei den beiden die angerufen haben ist es durch manuelle Eingabe der Domain gelöst.

Außerdem dürfte das doch eigentlich nix mit Caching zu tun haben oder?

Ich mein wenn ich das hier in unter AddOpenIdConnection habe, kann es doch eigentlich nicht sein, dass die code challenge bei einigen nicht ausgeführt wird:


                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                    {
                        var codeVerifier = CryptoRandom.CreateUniqueId(32);

                        context.Properties.Items.Add("code_verifier", codeVerifier);

                        string codeChallenge;
                        using (var sha256 = SHA256.Create())
                        {
                            var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                            codeChallenge = Base64Url.Encode(challengeBytes);
                        }

                        context.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
                        context.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
                    }

                    return Task.CompletedTask;
                };

                options.Events.OnAuthorizationCodeReceived = context =>
                {
                    if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                    {
                        if (context.Properties.Items.TryGetValue("code_verifier", out var codeVerifier))
                        {
                            context.TokenEndpointRequest.Parameters.Add("code_verifier", codeVerifier);
                        }
                    }

                    return Task.CompletedTask;
                };

Ich habs auch schon auf replicas 1 gesetzt um sicherzustellen, dass nicht irgendwer auf eine alte Version zugreift.
Kann wirklich nicht nachvollziehen woher der Fehler kommen kann.

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 3 Jahren

Verwendest Du ASP.NET Core 2 oder 3?

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 3 Jahren

3.1, ich weiß auch, dass das mit UsePkce out of the Box funktioniert.

Hab jetzt nur testweise die händische Implementierung nochmal getestet. Das Ergebnis ist bei beiden aber das gleiche.

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 3 Jahren

Wie sieht Deine Config aus?

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 3 Jahren

        public static IServiceCollection ConfigureIdentityServices(this IServiceCollection services, IConfigurationRoot configuration)
        {
            var settings = configuration.GetConfiguration<OpenIdConnectOptions>();
            var client = configuration.GetConfiguration<OAuthClient>();

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = settings.SignInScheme;
                options.DefaultScheme = settings.SignInScheme;
                options.DefaultChallengeScheme = settings.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromSeconds(2592000);
                options.Cookie.Name = settings.CookieName;
                options.Cookie.IsEssential = true;
                options.AccessDeniedPath = "/account/accessdenied";
                options.LoginPath = "/account/login";
                options.SlidingExpiration = true;
            })
            .AddAutomaticTokenManagement()
            .AddOpenIdConnect(settings.AuthenticationScheme, options =>
            {
                options.Authority = settings.Authority;
                options.RequireHttpsMetadata = settings.RequireHttpsMetadata;

                options.CallbackPath = new PathString(settings.CallbackPath);
                options.SignedOutCallbackPath = new PathString(settings.SignedOutCallbackPath);
                options.RemoteSignOutPath = new PathString(settings.RemoteSignOutPath);
                options.ClientId = client.ClientId;
                options.ClientSecret = client.ClientSecret;
                options.ResponseType = settings.ResponseType;
                options.ResponseMode = settings.ResponseMode;

                foreach (var scope in settings.Scopes)
                {
                    options.Scope.Add(scope);
                }

                options.GetClaimsFromUserInfoEndpoint = settings.GetClaimsFromUserInfoEndpoint;
                options.SaveTokens = settings.SaveTokens;
                options.TokenValidationParameters = settings.TokenParameter;

                options.ClaimActions.MapAllExcept("role", "iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash", "auth_time", "idp", "amr");
                options.ClaimActions.Add(new Helpers.JsonKeyClaimAction(JwtClaimTypes.Role, null, JwtClaimTypes.Role));

                options.UsePkce = settings.UsePkce;
                /*
                 * .netcore2.1 approach
                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                    {
                        var codeVerifier = CryptoRandom.CreateUniqueId(32);

                        context.Properties.Items.Add("code_verifier", codeVerifier);

                        string codeChallenge;
                        using (var sha256 = SHA256.Create())
                        {
                            var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                            codeChallenge = Base64Url.Encode(challengeBytes);
                        }

                        context.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
                        context.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
                    }

                    return Task.CompletedTask;
                };

                options.Events.OnAuthorizationCodeReceived = context =>
                {
                    if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                    {
                        if (context.Properties.Items.TryGetValue("code_verifier", out var codeVerifier))
                        {
                            context.TokenEndpointRequest.Parameters.Add("code_verifier", codeVerifier);
                        }
                    }

                    return Task.CompletedTask;
                };
                */
            });

            services.AddHttpClient();
            services.AddSingleton<IDiscoveryCache>(r =>
            {
                var factory = r.GetRequiredService<IHttpClientFactory>();
                return new DiscoveryCache(settings.Authority, () => factory.CreateClient());
            });

            return services;
        }

appsettings.json


  "OpenIdConnect": {
    "AuthenticationScheme": "oidc",
    "SignInScheme": "Cookies",
    "CookieName": "fmid",
    "Authority": "https://login.domain.com",
    "RequireHttpsMetadata": "true",
    "CallbackPath": "/signin-oidc",
    "SignedOutCallbackPath": "/signout-callback-oidc",
    "RemoteSignOutPath": "/signout-oidc",
    "ResponseType": "code",
    "ResponseMode": "form_post",
    "UsePkce": "true",
    "GetClaimsFromUserInfoEndpoint": "true",
    "Prompt": "login",
    "SaveTokens": "true",
    "Scopes": [ "profile", "openid", "offline_access", "api_access" ],
    "TokenParameter": {
      "NameClaimType": "name",
      "RoleClaimType": "role"
    }

appsettings.secret.json


  "OAuthClient": {
    "Issuer": "login.domain.com",
    "ClientId": "idf_web_client",
    "ClientSecret": "change-this-in-production"
  }

2+2=5( (für extrem große Werte von 2)

16.807 Beiträge seit 2008
vor 3 Jahren

Okay, sehe ich so auch nichts...

Hätte gedacht, dass evtl. ResponseType falsch ist oder was anderes auffällt.

P
441 Beiträge seit 2014
vor 3 Jahren

Hast du an das einfachste Gedacht?

Wie sieht denn die Bookmark aus? Ist das vielleicht der Redirect zum Identity Provider?

emuuu Themenstarter:in
286 Beiträge seit 2011
vor 3 Jahren

Ist das vielleicht der Redirect zum Identity Provider?

Jop, ist es aber nicht. Das würde auch aber auch einen anderen Fehler verursachen (invalid client oder so), da der Client jetzt einen anderen Flow verwendet. Wenn sich jemand sich den Redirect gebookmarked hätte, wäre in der Request-URL noch der alte Flow hinterlegt (konkret meine ich das id_token im response type).

2+2=5( (für extrem große Werte von 2)