Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von emuuu
Thema: Habt ihr Erfahrungen mit Authorization aware HATEOAS?
Am im Forum: Web-Technologien

Zitat von Abt
In der Praxis findet aber HATEOAS kaum Anwendung, weil es schon auch große Nachteile hat:
Super erstmal danke für die Hinweise. Hab mir bewusst ein kleines Projekt gesucht, wo eine mögliche Überkomplexität, am Ende keine Beine bricht. Ich will vor allem ein Gefühl für Nutzen und Aufwand kriegen, um im Zweifel dann dafür oder dagegen argumentieren zu können.
Zitat von Abt
Ansonsten weiß ich nicht, was Du mit Geschäftslogik meinst; denn in de Links wird nur der State übertragen.
Damit meine ich ganz platt in welcher Form die Informationen innerhalb der API weitergereicht / zusammengetragen werden.
Wenn ich z.B. in einer response die Links von drei verschiedenen Controllern habe und bei einem nested object kann der user aufgrund der authorization editieren, bei zweien deleten und die restlichen nur get.
Ich weiß momentan nicht an welcher Stelle in der API ich die Kenntnis über alle möglichen Links + die Authorization zusammentragen würde.
Zitat von Abt
Gib Deine API Klassen niemans ein Suffix wie DTO, sondern arbeite einfach mit einem spezifischen Namen wie "Product" und einem sauberen Namespace.
Wie siehts da mit z.B. create- und update-klassen aus? ProductCreate, ProductUpdate?

Wenn ich für unterschiedliche authorization unterschiedliche Details ausgebe (bsp Kunde kann nur Name, Preis, etc sehen, Produzent die Parts, Teilenummer, usw.):
Ich verwende dafür unterschiedliche Klassen Product, ProductForManager. Wie verträgt sich das mit doc discovery?

Thema: Habt ihr Erfahrungen mit Authorization aware HATEOAS?
Am im Forum: Web-Technologien

Guten Tag zusammen,

wie der Titel schon sagt beschäftige ich mich momentan mit authorization aware hateoas (tl;dr; anstatt alle möglichen transitions gibt der server nur die im aktuell authorization context gültigen transitions zurück -> Kunde kann Produkte abfragen aber nicht updaten)
und würde das in einem neuen Projekt gerne anwenden. Das Grundprinzip ist ja relativ simpel.
Meine Frage wäre nun, ob wer von euch damit schon Erfahrungen hat und optimalerweise irgendwelche examples hat / kennt.

Mich interessiert dabei vor allem die Projektstruktur und Zugriffsebenen:
Die Links kennt imho nur der Controller die Authorization hingegen liegt um untergeordneten business layer.

Und wie sieht es mit nested objects aus? Wenn ich bsp folgendes Dto habe:


public class ProductDto
{
   public int Id {get;set;}

   [..]

   public IEnumerable<PartDto> Parts {get;set;}
}
Mir ist noch nicht ganz klar, wie ich die Information über die möglichen transitions (die beim PartDto z.B. aus einem anderen Controller kommen als für ProductDto aufgerufen wurde) in die Geschäftslogik und wieder zurück kriege (ohne gegen Konventionen zu verstoßen).

Natürlich wird es hier nicht den einen richtigen Weg geben und es ist immer von den weiteren Anforderungen anhängig. Aber mir fehlts dahingehend momentan an einem Grundgerüst, das man weiterentwickeln kann.

Beste Grüße
emuuu

Thema: Happy .NET 5 day
Am im Forum: Szenenews

Wundert mich, dass es noch keine News dazu gab, darum hier in aller Kürze:
Heute launched .NET 5 auf der .NET Conf 2020 :]

Thema: Welche(s) Framework(s) für Desktop & Mobile Entwicklung?
Am im Forum: Cross Platform Entwicklung - Mobile und IoT

Zitat von Palladin007
Für eine "richtige" Cross-Plattform-UI soll MAUI kommen, aber das steht noch aus.
Xamarin kann nach meinem letzten Stand nur mobile Geräte, keinen Desktop und wird nach .NET 6 auch recht bald sein Ende finden, da es ja durch MAUI abgelöst werden soll.

Xamarin kann mit Forms iOS, macOS, Android & UWP ist also stand jetzt schon absolut Cross-Plattform fähig. Du kannst damit quasi auf alles aktuelle außer Linux & exotische Smartphone OS (e.g. HarmonyOS von Huawei).
Habe eine App die ich problemlos auf einem Windows-PC ebenso wie auf einem iPhone deployen kann.

MAUI löst Xamarin auch imho nicht ab sondern ist ein rebranding (Microsoft hat Xamarin gekauft und schließt damit quasi die Einbindung in die eigene Produktfamilie ab).
Unter der Haube wird sich nicht allzu viel ändern.

Thema: Warum sind 1kB = 1024 Byte?
Am im Forum: Smalltalk

Zitat von HansFred
ganz schön freche antwort wenn man bedenkt das man dir helfen will. ich denke du kannst es einfach nicht kapieren oder willst es nicht kapieren.

Ich empfinde deine Antworten eher als extrem herablassend und mit gefährlichem Halbwissen gespickt.
Zitat von HansFred
Kilo hat 10 bytes also heisst es ausgesprochen 2 hoch 10 Bytes = 1024 Bytes

Das ist vollkommener Quatsch. Man sagt zu 2^10 Bytes wie ayykaramba schon richtig gesagt hat einfach umgangssprachlich Kilo, weil 10^3 am nächsten dran an 2^10 ist. Und die SI-Präfixe waren damals einfach extrem verbreitet und daher hat sich das durchgesetzt.

Mit dem Aufkommen der TB-Festplatteten haben die Hersteller sich das direkt zu nutze gemacht und bei einer 1 TB-HDD nur 1000 GB anstatt 1024 GB reingepackt.

Thema: Corona-Inzidenz-Widget für iOS
Am im Forum: .NET-Komponenten und C#-Snippets

Moin zusammen,

bin gerade über dieses schöne Repo zum Erstellen eines Widgets, welche die Corona-Fallzahlen + die Inzidenz für den Aufenthaltsort anzeigt, gestolpert:
incidens_and_newcases.js

Ihr benötigt dafür die App Scriptable (eine genaue Anleitung ist im gist enthalten)

Ich kenne mich mit Android-Widgets nicht aus, aber da das Script in js ist, sollte es sich relativ leicht für Android anpassen lassen.

Beste Grüße
emuuu


Edit:
Hier ist der Original-Code der auch zahlreiche Forks mit verschiedenen, fertigen Varianten (mit Bildern) auflistet.

Thema: Einfaches Repository für MongoDB-Anwendungen
Am im Forum: Code-Reviews

Zitat von Abt
Auch wenn der Client zB 10.000 Einträge will, würde man nur 1000 zurück geben.
Macht man allgemein beim API Design so (auch bei REST und Co..).

Im Allgemeinen ist mir das klar, aber hierbei geht es ja um eine Klassenbibliothek, die man als Teil eines Projektes nutzen soll.
Sollte ich da nicht eher dem Anwender überlassen wie er die Pagination in seinem Service limitiert? Es ist ja eher ein Tool, das noch konfiguriert / benutzt werden soll als eine fertige Lösung.

Thema: Einfaches Repository für MongoDB-Anwendungen
Am im Forum: Code-Reviews

Hier mal die Variante mit Filter / Sort via Linq:


public virtual async Task<IList<TEntity>> GetAll<TProperty>(Expression<Func<TEntity, bool>> filter, Expression<Func<TEntity, TProperty>> sorting, int? page = null, int? pageSize = null)
		{
			IList<TEntity> result = await Collection
				.AsQueryable()
				.Where(filter)
				.OrderBy(sorting)
				.ToListAsync().ConfigureAwait(false);

			if(page.HasValue && pageSize.HasValue)
            {
				if (page < 1)
				{
					page = 1;
				}
				if (pageSize < 1)
				{
					pageSize = 1;
				}

				result = result
				.Skip((page.Value - 1) * pageSize.Value)
				.Take(pageSize.Value)
				.ToList();
			}
			return result;
		}
TProperty wird benötigt, da TKey auf eine contravariant wäre (da bereits verwendet).

Spricht was gegen den Ansatz? (ThenBy würde ich in einem separaten overload implementieren)

Wie sieht es eigentlich in Richtung best practices aus, was die parameter angeht? Sollte ich lieber für jede Variante nen eigenen overload erstellen oder so wie bisher alles gleichzeitig aufnehmen und nen null-Value einfach handlen?

Thema: MongoDB filter mit eigenem Interpreter erstellen
Am im Forum: Datentechnologien

Guten Tag zusammen,

ich hatte hier schon mal mein Mongo repository gepostet für das ich momentan versuche eine Erweiterung zu bauen.

Da der Service der das Mongo repository anspricht selbst nur eine Zwischenschicht ist die via gRPC angesprochen wird brauche ich eine Möglichkeit FilterDefinitions vom gRPC client an den Service zu übertragen.
Iirc ist es kaum möglich Builder<FooBarClass>.Filter.Eq("Foo", "Bar") direkt im protobuf zu definieren.

Ich müsste also eine Abstraktion für Filterregeln erstellen und diese dann übertragen, also sowas in die Richtung:


message Filter {
  string field = 1;
  repeated string values = 2;
  string operator = 3;
  bool strongRequired = 4;
}

message FilteredRequest {
  repeated Filter filters = 1;
}


Da ich das Rad nicht unbedingt neu erfinden will wäre meine Frage:
Welchen Ansatz würdet ihr nehmen? Oder gibt es bereits was Ähnliches, an das man anknüpfen könnte?
Vllt verwende ich nur die falschen Suchbegriffe aber für den konkreten Fall finde ich bisher so gut wie gar nix.

Beste Grüße
emuuu

P.s. ich habe eine funktionierende Lösung in der ich auf client Seite einen Builder erstelle, den in einen json string umwandle, diesen übertrage und das ganze auf der anderen Seite mit JsonFilterDefinition<FooBarClass> verwende. Finde ich aber irgendwie unelegant.

Thema: Azure CosmosDB - Anwendungsbereiche | Kosten
Am im Forum: Smalltalk

Zitat von Abt
- Bei CosmosDB erhälst Du eine Garantie auf eine Leistung (die genannten Request Units).
- Bei MongoDB Atlas erhälst Du die freie Verfügung über Ressourcen.

Der Teil ist mir bewusst und wenn ich sage ich hab mich noch nicht so sehr beschäftigt, dann meine ich vor allem dass die RUs für mich noch etwas mystisch sind.

Ich habe aktuell einen einzigen MSSQL der insgesamt knapp 5gb hat und ca 30k requests pro Tag frisst, lokal gehostet in einem Swarm. Also nix Großes.

Und die möchte ich eben der Reihe nach auskoppeln und suche gerade nach einer noSQL-Lösung.

Thema: Azure CosmosDB - Anwendungsbereiche | Kosten
Am im Forum: Smalltalk

Guten Tag zusammen,

wollte man nach euren Erfahrungen mit CosmosDB fragen, vor allem in Bezug auf Kosteneffizienz.
Habe jetzt mal eine DB als Test im Free-Tier erstellt und bin etwas irritiert über die Kosten:
Eine Collection mit einem Document, dass eine Größe von 65 kB hat -> 1,36$ pro Tag.

Ich hab mich jetzt noch nicht mit dem weiteren pricing beschäftigt, aber wenn eine Test DB in der ich wirklich nicht viel gemacht hat mir direkt ~40 $ / Monat um die Ohren haut, bin ich direkt nicht sehr motiviert für mehr. Oder verstehe ich die Verwendung oder die Vorteile von CosmosDB falsch? (Azure sagt sie haben keine Optimierungsvorschläge).

Ich meine wenn ich das mit MongoDB Atlas vergleiche zahle ich für nen Cluster mit sharedCPU/RAM und 2GB storage 9$ /month.

Finde den Unterschied schon sehr gravierend. Oder hat CosmosDB einfach irgendwelche überragenden perks die ich nicht hoch genug wertschätze?

Beste Grüße
emuuu

Thema: Einfaches Repository für MongoDB-Anwendungen
Am im Forum: Code-Reviews

Super, danke schon mal für das Feedback, gerade in Bezug auf Konventionen, da ich da noch nicht so firm bin.

Die eigenen commit messages, mache ich immer auf Englisch, allerdings habe ich den initial commit über das GitHub-plugin von VS erstellt, vermute dass das auf DE localed ist. Da muss ich mir nochmal die Einstellungen anschauen.

Zitat von Abt
Feedback:
- Deine Methoden sind alle Fire-and-Forget aufgebaut. Der Verwender hat keine Chance die Results der MongoDB Operationen zu erhalten.
Meinst du damit, dass ich await Collection.... direkt zurückgebe?

Thema: Einfaches Repository für MongoDB-Anwendungen
Am im Forum: Code-Reviews

Guten Morgen zusammen,

ich habe für meine Anwendung ein einfaches (MongoDB-)Repository erstellt, dass CRUD liefert und beliebig erweitert werden kann.
Für mich ist Ziel des Ganzen, dass ich in einer Microservice-Umgebung möglichst unkompliziert einen neuen Service erstellen kann, der eine einzige Enity verwaltet erstellen kann.

MongoRepository
Kritik, Anregungen und vor allem Verbesserungsvorschläge sind willkommen.

Beste Grüße
emuuu

Thema: [gelöst] gRPC-Server antwortet SEHR langsam
Am im Forum: Netzwerktechnologien

Zitat von Abt
Auch schon davor, oder erst jetzt nach Deinem Edit um 16:07 Uhr?
Problem nun mit der richtigen Krestel-Config gelöst?

Jop das Problem besteht wenn ich in der Program.cs im CreateHostBuilder .UseKestrel verwende.
Wenn ich stattdessen .ConfigureKestrel (wie im edit) verwende, funktioniert es.

Thema: [gelöst] gRPC-Server antwortet SEHR langsam
Am im Forum: Netzwerktechnologien

Zitat von Abt
Wie sieht die originale Startup.Configure() Methode aus?
Das UseKestrel kommt bei mir aus der Program.cs
Zitat von Abt
Welche ASP.NET Core Version hast Du denn?
3.1
Zitat von Abt
Weil Kestrel wird in den neueren Versionen über den Host Builder konfiguriert und nicht über Configure().
Da hab ichs auch drin, aber eben mit webBuilder.UseKestrel() anstatt .ConfigureKestrel


        private static IHostBuilder CreateHostBuilder(IConfigurationRoot configuration, string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
            //..
            })

Thema: [gelöst] gRPC-Server antwortet SEHR langsam
Am im Forum: Netzwerktechnologien

Die Anfrage an den grpc-Server dauert so lang:


//2000ms:
await client.GetAllToolsAsync(new AllToolsRequest())

Auf der anderen ist der grpc-Server in der Verarbeitung aber recht zügig:


//22ms:
public override async Task<MultipleToolReply> GetAllTools(AllToolsRequest request, ServerCallContext context)
{
//..
}

Was also so lang dauert ist die reine Übertragung. Es muss etwas mit .UseKestrel zu tun haben.
Wen ich den Teil komplett rausnehme kriege ich eine vernünftige ResponseTime

Update:
Ok, irgendwie ist UseKestrel broke.
Wenn ich


   .UseKestrel(options =>
   {
      options.Listen(IPAddress.Any, ports.grpcPort, listenOptions =>
      {
         listenOptions.Protocols = HttpProtocols.Http2;
         listenOptions.UseHttps($"/etc/certs/{serviceName}.p12", serviceName);
      });
   })
durch


   .ConfigureKestrel(options =>
   {
      options.ListenAnyIP(ports.grpcPort, o =>
      {
         o.Protocols = HttpProtocols.Http2;
         o.UseHttps($"/etc/certs/{serviceName}.p12", serviceName);
      });
   })
ersetze, funktioniert es problemlos

Thema: [gelöst] gRPC-Server antwortet SEHR langsam
Am im Forum: Netzwerktechnologien

Guten Tag zusammen,

ich habe ein Problem mit gRPC in folgendem Setup:
Api-Gateway <-> gRPC-Server <-> Azure CosmosDB

Die API sowie den gRPC-Server lasse ich beide auf localhost laufen (mit tls). Das Problem nun: Selbst wenn beides Services hot sind dauert eine GetAll-Response (377 Byte response body) 2,08 Sekunden.

Hab jetzt die Dauer der einzelnen Schritte analysiert und hier die Bremse idenzifiziert:


        public async Task<List<ToolDto>> GetAll()
        {
            return await GrpcCallerService.CallService(_urls.GrpcTools, async channel =>
            {
                var client = new ToolStore.ToolStoreClient(channel);
                var response = await client.GetAllToolsAsync(new AllToolsRequest()); //dauert ~2000ms
                return response.Tools.Select(x => _mapper.Map<ToolDto>(x)).ToList();
            });
        }

Auf der anderen Seite von AllToolsRequest antwortet braucht der gRPC-Server allerdings nur ~22ms zum verarbeiten:


        public override async Task<MultipleToolReply> GetAllTools(AllToolsRequest request, ServerCallContext context)
        {
            try
            {
                var tools = await _toolRepository.GetAll();

                var result = new MultipleToolReply();
                result.Tools.AddRange(tools.Select(x => _mapper.Map<ToolReply>(x)));
                return result;
            }
            catch (Exception ex)
            {
                throw new RpcException(new Status(StatusCode.Internal, ex.Message));
            }
        }

Das Problem muss im gRPC-Server verortet sein, da ich bei abrufen mit 3rd party tools wie bloomRPC auf die gleichen response Zeiten komme.
Sprich irgendwas in der Übertragung ist extrem langsam. Habt ihr irgendeine Idee woran das liegen kann?

gRPC-Server:
Program.cs


                .UseKestrel(options =>
                {
                    var ports = GetDefinedPorts(configuration);

                    var serviceName = Environment.GetEnvironmentVariable("service_name") ?? "localhost";

                    options.Listen(IPAddress.Any, ports.grpcPort, listenOptions =>
                    {
                        listenOptions.Protocols = HttpProtocols.Http2;
                        listenOptions.UseHttps($"/etc/certs/{serviceName}.p12", serviceName);
                    });
                })

Startup.cs


            services.AddGrpc();

            //...
            app.UseEndpoints(endpoints =>
            {
                GrpcEndpointRouteBuilderExtensions.MapGrpcService<ToolService>(endpoints);
            });

Beste Grüße
emuuu

Thema: Soll ein WebService in Container hinter Proxy TLS nutzen oder nicht?
Am im Forum: Web-Technologien

Kleines Update dazu:
Es gibt von Cloudflare ein Docker image für eine CA:
GitHub
DockerHub

Die platziere ich im gleichen Docker stack und vertraue ihr mit allen Services. Für die Microservices schreibe ich ins Dockerfile ein Script, dass im Volume nach einem Zertifikat sucht und andernfalls eins beim CA-Service anfragt und in die ins Volume schreibt.

Weder die CA noch die Microservices sind außerhalb des stack-networks erreichbar.

Thema: Blazor Transistions between pages
Am im Forum: .NET-Komponenten und C#-Snippets

Guten Abend zusammen,

ich bin gerade über was hübsches für Blazor gestolpert:
BlazorTransitionableRoute
nuget package


blazor transition pages

Thema: Einbinden von Client-Hardware in Blazor
Am im Forum: Web-Technologien

Guten Tag zusammen,

ich bastle gerade an einem IoT-Projekt bei dem ich auf einem RaspberryPi eine Blazor-App auf localhost laufen lassen möchte.

Die Frage ist nun: Ob und wie kann ich die Nutzung vom weiterer Hardware am raspi unterstützen. Beispielsweise die Anbindung von einem NFC/RFID-Leser.

Also zwei Szenarien:
1. Klick in Blazor-App -> Aktiviere / Lese NFC -> result an die App
2. NFC-Leser findet was Lesbares -> push an die App

Vor alle zweites Szenario fände ich interessanter, aber vermutlich auch komplexer.
Habt ihr da Erfahrungen / Erkenntnisse?

Beste Grüße
emuuu

Thema: c# openid connect client
Am im Forum: Web-Technologien

Es ist halt schon lustig, dass wirklich der LETZTE Eintrag vor deinem dir exakt die Antwort liefert die du brauchst..

So in Richtung Regeln und Forensuche........

Und wenn dir das als Antwort nicht präzise genug ist: Du sagst so gut wie gar nichts über deine Umgebung bzw. was du machen möchtest.
C# ist in erster Linie nur eine Sprache. Ohne ein Framework bzw eine Plattform zu bestimmen ist es mehr oder minder unmöglich dir einen Lösungsansatz zu liefern.

Da du in Webtechnologien gepostet hast ist vermutlich ASP.NET Core 3 dein weg und damit wäre AddOpenIdConnect() dein Weg.

Beste Grüße emuuu

Thema: Chrome - Werden Websites über Bookmarks gecached?
Am im Forum: Web-Technologien

Zitat von Papst
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).

Thema: Github schließt Archivierung im Eis ab
Am im Forum: Szenenews

Die Meldung ist jetzt schon eine Woche alt, aber GitHub hat seine Arktis-Archivierung abgeschlossen:
GitHub schließt Archivierung im Eis ab

Gilt für alle öffentlichen Repositories und alle Contributors erhalten ein Badge. Habe es jetzt selbst erstmal angezeigt bekommen:

Thema: Chrome - Werden Websites über Bookmarks gecached?
Am im Forum: Web-Technologien


        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"
  }

Thema: Chrome - Werden Websites über Bookmarks gecached?
Am im Forum: Web-Technologien

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.

Thema: Chrome - Werden Websites über Bookmarks gecached?
Am im Forum: Web-Technologien

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.

Thema: Chrome - Werden Websites über Bookmarks gecached?
Am im Forum: Web-Technologien

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

Thema: Verwaltung von Docker-Containern/Swarm: Erfahrungen mit Portainer
Am im Forum: Rund um die Programmierung

Guten Tag zusammen,

ich wollte mal fragen, ob wer von euch Erfahrungen mit Portainer hat und für welchen UseCase ihr das (nicht) empfehlen würdet.

Auf den ersten Blick liefert mir das nur ein hübsches GUI für Cluster und erspart mir ein bisschen CLI. Das wären für mich jetzt beides keine abschließenden Argumente das einzusetzen.

Gibt es da noch sonstige Punkt die dafür/dagegen sprechen?


Beste Grüße
emuuu

Thema: Soll ein WebService in Container hinter Proxy TLS nutzen oder nicht?
Am im Forum: Web-Technologien

Was wäre denn der korrekte Weg um Zertifikate zu erstellen, mit denen sich die Container untereinander vertrauen können?
Wenn ich innerhalb des Swarms z.B. mehrere Services habe die über gRPC miteinander reden und mehrere Gateways die dieses wiederum via https ansprechen?

Ich könnte jedem Service im docker-compose einen festen Network-Alias mitgeben für den ich ein Zertifikat erstelle. Aber wo platziere ich die CA dafür und bringe den Services bei dieser zu vertrauen?

Thema: Soll ein WebService in Container hinter Proxy TLS nutzen oder nicht?
Am im Forum: Web-Technologien

Ok, danke für die Info, habe ich mir schon fast so gedacht - aber Feedback ist da doch hilfreich.

Eine Frage noch zu praktischen Umsetzung: Kann ich einfach ein eigenes Zertifikat erstellen, dem Swarm als Secret mitgeben und dann einfach bei allen relevanten Services einfach folgendes machen:


    environment:
        ASPNETCORE_Kestrel__Certificates__Default__Path: /run/secrets/https-certificate
        ASPNETCORE_Kestrel__Certificates__Default__Password: /run/secrets/https-certificate-password
        ASPNETCORE_URLS: 'https://+;http://+'
        ASPNETCORE_HTTPS_PORT: 443

Oder sollte ich für jeden Service ein eigenes Zertifikat erstellen (wenn eins corrupted wird wären es doch ohnehin alle - da am gleichen Ort hinterlegt)