myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Web-Technologien » ASP.NET Core 3.1 Cookie Authentication leitet mich wieder zum Login zurück
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

ASP.NET Core 3.1 Cookie Authentication leitet mich wieder zum Login zurück

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Duesmannr Duesmannr ist männlich
myCSharp.de-Mitglied

Dabei seit: 28.04.2017
Beiträge: 104
Entwicklungsumgebung: Visual Studio 2017/19
Herkunft: Münster


Duesmannr ist offline

ASP.NET Core 3.1 Cookie Authentication leitet mich wieder zum Login zurück

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hey, ich schon wieder^^

Das Problem ist, wenn ich mich erfolgreich authentifiziere und ich mich mit SignInAsync anmelde, werde ich zum HomeController weitergeleitet.
Das Authorize leitet mich direkt wieder zur Login Page zurück, weil weiß ich nicht.

Die ValidateAsync Methode habe ich überprüft, das Cookie wird nicht rejected oder ich werde ausgeloggt.

Ich habe es auch mit einem Custom Authorize Attribute getestet um den Context zu überprüfen.
In dem Context bin ich angemeldet und authenticated.

Die Authentifizierung habe ich genau so in einem Asp.Net Core 2.1 Projekt und da läuft es einwandfrei..

Aber warum Authorize mich nicht durchlässt, ich weiß es nicht.
Habt Ihr Ideen?

Hier ist die Konfiguration:

HomeController.cs

C#-Code:
public class HomeController : Controller
{
    [Authorize]
    public IActionResult Index()
    {
        return this.View("Index");
    }
}

Startup.cs

C#-Code:
public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/auth/login/";
                options.ExpireTimeSpan = TimeSpan.FromDays(7);
                options.Events.OnValidatePrincipal = ValidateAsync;
            });

        services.AddControllersWithViews();

        services.AddAntiforgery();

        services.AddDbContext<ApplicationDbContext>((serviceProvider, options) =>
        {
            options.UseSqlServer(this.Configuration.GetConnectionString("DefaultConnection"));
            options.EnableSensitiveDataLogging();
        });
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if(env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        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.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();
        app.UseAuthentication();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }

public static async Task ValidateAsync(CookieValidatePrincipalContext context)
    {
        context = context ?? throw new ArgumentNullException(nameof(context));

        String userId = context.Principal.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier)?.Value;

        if(userId == null)
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return;
        }

        ApplicationDbContext dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
        User user = await dbContext.Users.FindAsync(Guid.Parse(userId));

        if(user == null)
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return;
        }

        if(!user.StaySignedIn &&
            user.LastLogin != null &&
            (user.LastLogin.Subtract(TimeSpan.FromDays(1)) > DateTimeOffset.Now))
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return;
        }
    }

AuthController.cs

C#-Code:
[Route("/login")]
    [Route("/auth/login")]
    public async Task<IActionResult> Login([FromForm]LoginModel loginModel)
    {
        Claim nameIdentifier = new Claim(ClaimTypes.NameIdentifier, user.Id.ToString());

        ClaimsIdentity userIdentity = new ClaimsIdentity(new List<Claim> { nameIdentifier }, CookieAuthenticationDefaults.AuthenticationScheme);
        ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(userIdentity);

        await this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
        return this.RedirectToAction("Index", "Home");
    }
19.02.2020 08:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Taipi88 Taipi88 ist männlich
myCSharp.de-Mitglied

avatar-3220.jpg


Dabei seit: 02.02.2010
Beiträge: 1.022
Entwicklungsumgebung: VS 2010
Herkunft: Mainz


Taipi88 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

im Grunde kann ich nicht wirklich weiterhelfen - du versuchst hier quasi eine manuelle Cookie-Authentifizierung oder?

Fakt ist: Was du dort tust ist kein für ASP.NET Core nachvollziehbarer Login, womit du eine Art Authentication-Loop für den User gebaut hast.

Beispiel:
User ruft Home/Index auf
-> ASP.NET Core stellt fest: User ist nicht angemeldet
-> ASP.NET Core verweist Auth/Login
User postet seine Credentials
-> Du denkst, dass du den Benutzer erfolgreich anmeldest
-> Du leitest wieder auf Home/Index um
-> siehe Schritt 1 (ASP.NET Core stellt fest: User ist nicht angemeldet) und der Loop beginnt von vorn

Falls du das mit manuellen Cookies machen möchtest würde ich dir folgende Seite empfehlen:
 https://docs.microsoft.com/de-de/aspnet/...=aspnetcore-3.1

LG
19.02.2020 10:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Duesmannr Duesmannr ist männlich
myCSharp.de-Mitglied

Dabei seit: 28.04.2017
Beiträge: 104
Entwicklungsumgebung: Visual Studio 2017/19
Herkunft: Münster

Themenstarter Thema begonnen von Duesmannr

Duesmannr ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Taipi88:
im Grunde kann ich nicht wirklich weiterhelfen - du versuchst hier quasi eine manuelle Cookie-Authentifizierung oder?

Ja versuche ich.

Zitat von Taipi88:
Fakt ist: Was du dort tust ist kein für ASP.NET Core nachvollziehbarer Login, womit du eine Art Authentication-Loop für den User gebaut hast.

In .Net Core 2.1 funktioniert es wunderbar. Nur in 3.1 nicht mehr.

Zitat von Taipi88:
-> Du denkst, dass du den Benutzer erfolgreich anmeldest

Ich denke? Was macht dann HttpContext.SignIn() ? Den User anmelden eig.

Zitat von Taipi88:
-> siehe Schritt 1 (ASP.NET Core stellt fest: User ist nicht angemeldet) und der Loop beginnt von vorn

Ich habe noch keine konkrete Information dazu gefunden, wie das Attribut den Zugriff authoriziert.

Zitat von Taipi88:
Falls du das mit manuellen Cookies machen möchtest würde ich dir folgende Seite empfehlen:
 https://docs.microsoft.com/de-de/aspnet/...=aspnetcore-3.1

Habe die Seite dabei die ganze Zeit offen :)

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Duesmannr am 19.02.2020 11:13.

19.02.2020 11:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.280
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Duesmannr:
Ja versuche ich.

Und wieso machst das, wenn ASP.NET bereits einen sicheren Automatismus hat?

Genau wegen solch potentiell fehlerbehafteten Implementierungen hat ASP.NET Core gewisse Implementierungen, die man nicht umgehen kann, darunter zB das Authorize Attribut.
Zu viele Lücken und Probleme gab es in der Vergangenheit mit Flickschusterei.

Zitat:
Ich habe noch keine konkrete Information dazu gefunden, wie das Attribut den Zugriff authoriziert

In der Dokumentation steht's.

Ansonsten hab ich solch ein Validation Code schon mehrfach hier im Forum gepostet und auch in  Warum IP-Adressen kein eindeutiges Merkmal sind dokumentiert.

Zitat:
Ich denke? Was macht dann HttpContext.SignIn() ? Den User anmelden eig.

"User Anmelden" gibt es im Web nicht.
SignIn setzt ein Cookie, mit dem ASP.NET dann von einem Identitätsmanagement spricht.
Ist der Cookie nicht da (was Du selbst kontrollieren kannst, wir nicht) oder fehlerhaft (was Du debuggen kannst, wir nicht) dann kann keine Identität erstellt werden.

Ein relativ grober Fehler ist jedoch Deine Middlewares: UseAuthentication muss vor UseAuthorization erfolgen.
Man kann nicht authorisieren wenn man nicht authentifziert hat.

Im Debug logging (beachte dazu das LogLevel) steht der Grund, wieso AuthN oder AuthZ fehltschlägt.
19.02.2020 12:43 Beiträge des Benutzers | zu Buddylist hinzufügen
Duesmannr Duesmannr ist männlich
myCSharp.de-Mitglied

Dabei seit: 28.04.2017
Beiträge: 104
Entwicklungsumgebung: Visual Studio 2017/19
Herkunft: Münster

Themenstarter Thema begonnen von Duesmannr

Duesmannr ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Abt:
Und wieso machst das, wenn ASP.NET bereits einen sicheren Automatismus hat?

Der ist sicher. Wo soll der unsichere Faktor sein? Das dass authorize Attribute mich derzeit immer wieder zur Login Page weiterleitet hat ja was zu bedeuten und ich will wissen was.

Zitat von Abt:
In der Dokumentation steht's.

Und wo genau?

Zitat von Abt:
Ansonsten hab ich solch ein Validation Code schon mehrfach hier im Forum gepostet und auch in  Warum IP-Adressen kein eindeutiges Merkmal sind dokumentiert.

Ich mache derzeit ja gar nichts mit IP-Adressen.

Zitat von Abt:
"User Anmelden" gibt es im Web nicht.

Das war grob formuliert.

Zitat von Abt:
Ein relativ grober Fehler ist jedoch Deine Middlewares: UseAuthentication muss vor UseAuthorization erfolgen.
Man kann nicht authorisieren wenn man nicht authentifziert hat.

Da stimme ich dir zu. Aber das es so wichtig ist, in welcher Reihenfolge man die Middleware used finde ich seltsam.

Edit: Ich hab es nun umgedreht und es funktioniert.
Das Authorize Attribute lässt mich nun durch. Daher verstehe ich dann immer noch nicht ganz genau, wo die Authentication unsicher sein soll.

Zitat von Abt:
Im Debug logging (beachte dazu das LogLevel) steht der Grund, wieso AuthN oder AuthZ fehltschlägt.

Dann debugge ich das nochmal genauer.

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Duesmannr am 19.02.2020 13:29.

19.02.2020 13:26 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.280
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Duesmannr:
Ich mache derzeit ja gar nichts mit IP-Adressen.

Hast kein Bock gehabt den Artikel zu lesen, wa? Augenzwinkern
Dann hättest gemerkt, dass es gar nicht um die IP Adressen selbst geht, sondern wie man eine Identität in ASP.NET korrekt validiert (eben nicht über die IP).
Dann hättest eventuell auch nen Code Ausschnitt (und die korrekte Implementierung) gesehen.

Denn was Du hier in OnValidatePrincipal machst ist genau das: Identitätsvalidierung.

Zitat von Duesmannr:
Aber das es so wichtig ist, in welcher Reihenfolge man die Middleware used finde ich seltsam.

Dann hast Du bislang nicht verstanden, wie das gesamte ASP.NET Core Pipeline Prinzip funktioniert.
Die Reihenfolge der Middleware ist der wichtigste Punkt des gesamten ASP.NET Frameworks.

Dein Code kann auch so nie unter 2.1 funktioniert haben, denn das Prinzip der Pipelines gibt es seit OWIN - und das ist so ca. 8 Jahre her.
Es war in 1.0, 1.1, 1.2, 2.0, 2.1 und auch in 3.0 und 3.1 komplett von der funktionalenweise her identisch.

Und mein persönliches empfinden ist, dass ich immer etwas Bauchschmerzen habe, wenn jemand eine eigene Identitätsverwaltung in ASP.NET schreibt - und dann die Grundprinzipien von ASP.NET noch nicht ganz verstanden hat.
Dahingehend eben auch meine Hinweise - auch aus Erfahrung.

Zitat von Duesmannr:
Das Authorize Attribute lässt mich nun durch. Daher verstehe ich dann immer noch nicht ganz genau, wo die Authentication unsicher sein soll.

Wie Du sicherlich mitbekommen hast, gab es in den letzten Jahren immer mehr Datenleaks aus dem Web; im Bereich ASP.NET meistens, weil die Leute einfach scheisse Achtung programmiert haben - nicht weil das Framework Bugs hatte.
Scheisse programmiert meist in dem Sinne, weil sie einfach kein Plan hatten, was sie machen - und sich meist auch überhaupt nicht damit beschäftigt sondern einfach drauf losgelegt haben.
Was soll dann auch dabei raus kommen...

Eines der größten Lücken war eine fehlerhafte Implementierung einer eigenen AuthorizeAttribute-Ableitung.
Daher hat das Team rund um Barry Dorrans beim Grunddesign von ASP.NET Core bereits sehr darauf geachtet, dass Security by Design verfolgt wird.

Und dazu gehört, dass gewisse Dinge in Sachen Security durch beschissenen Code einfach nicht mehr passieren kann, weshalb es zB. auch nicht mehr (so einfach) möglich ist ein eigenes Authorize Attribut zu haben (das dann eben scheisse ist).
Daher gibt es in ASP.NET Core auch die Policies, die den gleichen Zweck wie früher Custom Authorize Attribute erfüllen - nur eben unter dem Aspekt "Security by Design".

Auch andere Frameworks anderer Sprachen haben ähnliche Mechenismen angekündigt oder bereits implementiert - unter dem identischen Aspekt.

Und genau für diesen Gesamtzweck - Security by Design - gibt es ASP.NET Core Identity, das der allgemein empfohlene Weg für eine saubere Security by Design Lösung ist.
Es bringt eigene Provider mit, die man aber auch selbst im Rahmen der "Richtlinien" für eigene Bedürfnisse implementieren kann.

Entwickler wird man niemals dazu erziehen können, dass sie einfach mal 15 Minuten in die Dokumentation schauen.
Wenn man aber Frameworks so gestaltet, dass das Design keine groben Lücken zulässt, ist vielen schon geholfen.
--
Falls Du Dich weiter interessierst, dann schau die Vorträge von Barry Dorrans aka blowdart auf YouTube an.
19.02.2020 14:23 Beiträge des Benutzers | zu Buddylist hinzufügen
Duesmannr Duesmannr ist männlich
myCSharp.de-Mitglied

Dabei seit: 28.04.2017
Beiträge: 104
Entwicklungsumgebung: Visual Studio 2017/19
Herkunft: Münster

Themenstarter Thema begonnen von Duesmannr

Duesmannr ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Abt:
Dein Code kann auch so nie unter 2.1 funktioniert haben, denn das Prinzip der Pipelines gibt es seit OWIN - und das ist so ca. 8 Jahre her.

Doch. Ich hab es doch vor mir. Der Unterschied ist, dass kein Eintrag für

C#-Code:
app.UseAuthorization();

existiert. Sondern nur Authentication.

Zitat von Abt:
Eines der größten Lücken war eine fehlerhafte Implementierung einer eigenen AuthorizeAttribute-Ableitung.

Das ist ja etwas, was ich nicht tue. Ich nutze ja das Standard Authorize Attribute.

Zum Abschluss. Danke für den Input :)
19.02.2020 14:42 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.280
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Duesmannr:
Die Authentifizierung habe ich genau so in einem Asp.Net Core 2.1 Projekt

Zitat von Duesmannr:
Der Unterschied ist, dass kein Eintrag für app.UseAuthorization(); existiert. Sondern nur Authentication.

Kannst jetzt drehen und wenden wie Du willst; aber wenn Du was hinzufügst, dann war der Code eben nicht genau so. Daumen hoch
19.02.2020 14:53 Beiträge des Benutzers | zu Buddylist hinzufügen
Duesmannr Duesmannr ist männlich
myCSharp.de-Mitglied

Dabei seit: 28.04.2017
Beiträge: 104
Entwicklungsumgebung: Visual Studio 2017/19
Herkunft: Münster

Themenstarter Thema begonnen von Duesmannr

Duesmannr ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja da hast du Recht..^^
19.02.2020 14:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 8 Monate.
Der letzte Beitrag ist älter als 8 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 25.10.2020 02:52