Verwenden von Inhaber-Token und Cookie-Authentifizierung zusammen

68

Ich habe eine App für eine einzelne Seite - mehr oder weniger basierend auf der MVC5 SPA-Vorlage -, die Inhaber-Token zur Authentifizierung verwendet.

Die Site verfügt auch über einige herkömmliche MVC-Seiten, die gesichert werden müssen, jedoch die Cookie-Authentifizierung verwenden .

In Startup.Auth kann ich beide Arten der Autorisierung aktivieren:

app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOAuthBearerTokens(OAuthOptions);

Dies scheint jedoch einen Nebeneffekt zu haben, da bei jedem Senden einer AJAX-Anforderung vom SPA sowohl das Inhaber-Token im Header als auch das Cookie gesendet werden .

Das Verhalten, das ich wirklich möchte, ist, dass nur das Inhaber-Token für WebAPI-Aufrufe und nur das Cookie für MVC-Aufrufe verwendet wird.

Ich möchte auch, dass die MVC-Aufrufe auf eine Anmeldeseite umleiten, wenn sie nicht autorisiert sind (als CookieAuthenticationOption festgelegt), aber ich möchte natürlich nicht, dass dies beim Ausführen eines API-Aufrufs geschieht.

Gibt es eine Möglichkeit, diese Art der Authentifizierung im gemischten Modus in einer Anwendung durchzuführen? Vielleicht durch einen Pfad- / Routenfilter?

Appetere
quelle

Antworten:

50

Ich denke, ich habe das herausgefunden: -

Startup.Auth verkabelt die OWIN-Pipeline, daher ist es richtig, Cookies und Token dort einzuschließen. Eine Änderung an den Cookie-Optionen gibt jedoch den Authentifizierungstyp an, für den sie gelten sollen:

CookieOptions = new CookieAuthenticationOptions
{
  AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie   
};

Dann musste ich WebAPI so konfigurieren, dass nur Token verwendet werden:

public static void Configure(HttpConfiguration config)
{
   // Configure Web API to use only bearer token authentication.
   config.SuppressDefaultHostAuthentication();
   config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
}

Dies scheint zu erreichen, was ich will. WebAPI verwendet nur Inhaber-Token und keine Cookies, und einige herkömmliche MVC-Seiten verwenden Cookies, sobald sie angemeldet sind (mithilfe des AuthenticationManager).

Appetere
quelle
2
Steve, ich werde das Gleiche tun. Ein Problem, das ich habe, ist, dass das Cookie und das Token (dh der lokale Speicher) nicht mehr synchron sind. Mit anderen Worten, müssen Cookie und Token gleichzeitig ablaufen, oder gibt es einen Mechanismus, um ordnungsgemäß zu handeln, wenn der eine oder andere fehlt?
ThisGuy
4
Übrigens gibt es in CookieAuthenticationOptions auch eine Option namens "CookieHttpOnly", die verhindert, dass JavaScript das Cookie an Ihre API weitergibt.
ThisGuy
4
@Steve, möchte nur eines klarstellen. Verwenden Sie separate Anmeldeseiten in SPA- und MVC-Teilen? Oder können Sie dies über eine einzige Anmeldeseite erreichen? Wenn es ein Fall ist, wie machst du das?
Alexander Boychenko
3
@ThisGuy Das ist falsch. "CookieHttpOnly" verhindert einfach, dass der Wert des Cookies in JavaScript gelesen wird , und verhindert nicht, dass das Cookie auf eine AJAX-Anfrage gesendet wird.
Dan Turner
4
Für diejenigen, die sich fragen, warum SuppressDefaultHostAuthentication () und HostAuthenticationFilter nicht gefunden werden können: Sie müssen dieses Paket installieren: via nuget:Install-Package Microsoft.AspNet.WebApi.Owin
Benjamin Martin
1

Sie können dem Cookie ein JWT-Token hinzufügen (hier lautet der Name meines JWT-Token-Cookies "access_token") und nur eine solche Middleware erstellen

public class JwtCookieMiddleware
{
    private readonly RequestDelegate _next;

    public JwtCookieMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext ctx)
    {
        if (ctx.Request.Cookies.TryGetValue("access_token", out var accessToken))
        {
            if (!string.IsNullOrEmpty(accessToken))
            {
                string bearerToken = String.Format("Bearer {0}", accessToken);
                ctx.Request.Headers.Add("Authorization",bearerToken);
            }
        }
        return this._next(ctx);
    }
}
public static class JwtCookieMiddlewareExtensions
{
    public static IApplicationBuilder UseJwtCookie(this IApplicationBuilder build)
    {
        return build.UseMiddleware<JwtCookieMiddleware>();
    }
}

Und Sie müssen die Middleware beim Start wie folgt verwenden:

app.UseJwtCookie();
app.UseAuthentification();
app.UseMvc();

Der obige Code fügt dem HTTP-Anforderungsheader ein JWT-Token hinzu, wenn diese Anforderung ein Token-Cookie enthält.

xiongkailing
quelle
3
Ich glaube, die Frage ist nicht über asp.net Kern
Anatol