Registrieren von externen Web API 2-Anmeldungen von mehreren API-Clients mit OWIN-Identität


75

Ich möchte die folgende Architektur (ich habe den Produktnamen für dieses Beispiel erfunden):

Web API 2-Anwendung, die auf einem Server ausgeführt wird http://api.prettypictures.com

MVC 5-Client-App, die auf einem anderen Server ausgeführt wird http://www.webpics.com

Ich möchte, dass die Client-App www.webpics.com die Pretty Pictures-API verwendet, um:

  • Registrieren Sie neue Konten mit Benutzername und Passwort
  • Registrieren Sie neue Konten bei Facebook / Google / Twitter / Microsoft
  • Einloggen
  • Bilder abrufen

Alle oben genannten Funktionen funktionieren außer der Registrierung externer Konten bei Facebook, Google usw.

Ich kann nicht den richtigen Ablauf ermitteln, um ein externes Konto von einem separaten Clientbenutzer der API zu erstellen .

Ich habe die meisten im Authentifizierungsablauf verfügbaren Dokumente wie folgt untersucht: Geben Sie hier die Bildbeschreibung ein

Ich habe so ziemlich alles gelesen, was ich über das neue Identitätsmodell in OWIN kann.

Ich habe die SPA-Vorlage in Visual Studio 2013 untersucht. Sie zeigt, wie ich das meiste tun kann, was ich brauche, aber nur, wenn sich der Client und die API auf demselben Host befinden. Wenn ich möchte, dass mehrere Clients auf meine API zugreifen und Benutzer sich über Google usw. anmelden können, funktioniert dies nicht und soweit ich das beurteilen kann, bricht der OWIN-Authentifizierungsablauf ab.

Hier ist der Fluss bisher:

  • Der Benutzer navigiert zu www.webpics.com/Login
  • www.webpics.com ruft api.prettypictures.com/Account/ExternalLogins auf (wobei ein returnUrl so eingestellt ist, dass es zu einem Rückruf unter www.webpics.com zurückkehrt ) und zeigt dem Benutzer die resultierenden Links an
  • Der Nutzer klickt auf "Google"
  • Der Browser leitet mit dem Namen des Anbieters usw. zu api.prettypictures.com/Account/ExternalLogin weiter .
  • Die ExternalLogin- Aktion der API instanziiert eine Herausforderung für google.com
  • Der Browser wird zu google.com umgeleitet
  • Der Nutzer gibt seinen Benutzernamen und sein Passwort ein (sofern er noch nicht bei google.com angemeldet ist ).
  • google.com präsentiert jetzt die Sicherheitsüberprüfung: "api.prettypictures.com" möchte Zugriff auf Ihre E-Mail-Adresse, Ihren Namen, Ihre Frau, Ihre Kinder usw. Ist das in Ordnung?
  • Der Benutzer klickt auf "Ja" und wird mit einem von Google gesetzten Cookie zu api.prettypictures.com/Account/ExternalLogin zurückgeführt .

Hier stecke ich fest. Was als nächstes passieren soll, ist, dass die Client-App benachrichtigt werden sollte, dass sich der Nutzer erfolgreich bei google.com authentifiziert hat, und einen einmaligen Zugangscode erhalten sollte, um später gegen ein Zugriffstoken auszutauschen. Die Client-App sollte bei Bedarf die Möglichkeit haben, den Benutzer zur Eingabe eines Benutzernamens aufzufordern, der mit seinem google.com- Login verknüpft werden soll .

Ich weiß nicht, wie ich das erleichtern soll.

Zu diesem Zeitpunkt befindet sich der Browser nach dem Rückruf von Google am Endpunkt api.prettypictures.com/Account/ExternalLogin . Die API ist für Google angemeldet, aber der Client weiß nicht, wie er damit umgehen soll. Soll ich diesen Cookie zurück zu www.webpics.com leiten ?

In der SPA-App erfolgt dies über AJAX und google.com gibt ein Token als URL-Fragment zurück und alles funktioniert einwandfrei, da sich alles auf einer Domain befindet. Dies widerspricht jedoch weitgehend dem Sinn einer "API", die mehrere Clients vollständig nutzen können.

Hilfe!


Hey Josh! Ich arbeite derzeit auch daran. Wir haben eine Web-API und ein HTML5 / AngularJS-SPA, die wir mit Google / Facebook authentifizieren möchten. Sie haben kein Blog oder Github-Repo mit einer Demo darüber, wie Sie das gelöst haben? Wäre sehr interessiert!
Ashkan Hovold

Hallo Ashkan, leider nicht! Führen Sie Ihr SPA in einer anderen Domäne als der Web-API aus (wie oben)?
Joshcomley

Ja, wir entwickeln eine Phonegap-App, sodass wir eine Web-API als Backend und ein reines HTML5 / AngularJS-SPA als Frontend für eine andere Domain haben. Dies wird später die App, die über Benutzertelefone auf die API zugreift.
Ashkan Hovold

Josh oder @AshkanAldini, haben Sie das gelöst? Ich versuche etwas Ähnliches zu tun und Pinpoints Antwort war hilfreich, aber ich bin immer noch verwirrt über die Implementierung.
Mayabelle

Antworten:


46

Update: Die Dinge haben sich geändert, seit ich diesen Beitrag im Januar geschrieben habe : MSFT hat die offizielle OpenID Connect-Client-Middleware veröffentlicht und ich habe hart mit @manfredsteyer zusammengearbeitet, um den in Katana integrierten OAuth2-Autorisierungsserver an OpenID Connect anzupassen. Diese Kombination führt zu einer weitaus einfacheren und leistungsstärkeren Lösung, die keinen benutzerdefinierten Clientcode erfordert und zu 100% mit Standard-OAuth2 / OpenID-Verbindungsclients kompatibel ist. Die verschiedenen Schritte, die ich im Januar erwähnt habe, können jetzt durch einige Zeilen ersetzt werden:

Server:

app.UseOpenIdConnectServer(options =>
{
    options.TokenEndpointPath = new PathString("/connect/token");
    options.SigningCredentials.AddCertificate(certificate);

    options.Provider = new CustomOpenIdConnectServerProvider();
});

Klient:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "http://localhost:55985/",

    ClientId = "myClient",
    ClientSecret = "secret_secret_secret",
    RedirectUri = "http://localhost:56854/oidc"
});

Sie finden alle Details (und verschiedene Beispiele) im GitHub-Repository:

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Nancy


Josh, Sie sind definitiv auf dem richtigen Weg und Ihre Implementierung der delegierten / föderierten Authentifizierung scheint ziemlich gut zu sein (ich stelle mir vor, Sie haben die vordefinierte OWIN-Middleware von verwendet Microsoft.Owin.Security.Facebook/Google/Twitter).

Sie müssen lediglich Ihren eigenen benutzerdefinierten OAuth2-Autorisierungsserver erstellen . Sie haben viele Möglichkeiten, um dies zu erreichen, aber die einfachste ist wahrscheinlich, die OAuthAuthorizationServerMiddlewareOWIN Startup-Klasse anzuschließen . Sie finden es im Microsoft.Owin.Security.OAuthNuget-Paket.

Während die beste Vorgehensweise darin besteht, ein separates Projekt zu erstellen (häufig als "AuthorizationServer" bezeichnet), ziehe ich es persönlich vor, es meinem "API-Projekt" hinzuzufügen, wenn es nicht für die Verwendung über mehrere APIs vorgesehen ist (hier müssten Sie es einfügen im Projekt Hosting "api.prettypictures.com").

Im Katana-Repository finden Sie ein großartiges Beispiel:

https://katanaproject.codeplex.com/SourceControl/latest#tests/Katana.Sandbox.WebServer/Startup.cs

app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
    AuthorizeEndpointPath = new PathString("/oauth2/authorize"),
    TokenEndpointPath = new PathString("/oauth2/token"),
    ApplicationCanDisplayErrors = true,

    AllowInsecureHttp = true,

    Provider = new OAuthAuthorizationServerProvider
    {
        OnValidateClientRedirectUri = ValidateClientRedirectUri,
        OnValidateClientAuthentication = ValidateClientAuthentication,
        OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
    },
    AuthorizationCodeProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateAuthenticationCode,
        OnReceive = ReceiveAuthenticationCode,
    },
    RefreshTokenProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateRefreshToken,
        OnReceive = ReceiveRefreshToken,
    }
});

Zögern Sie nicht, das gesamte Projekt zu durchsuchen, um zu sehen, wie das Autorisierungsgenehmigungsformular mithilfe einfacher Razor-Dateien implementiert wurde. Wenn Sie ein übergeordnetes Framework wie ASP.NET MVC oder NancyFX bevorzugen, erstellen Sie Ihren eigenen AuthorizationControllerController und Ihre eigenen AuthorizeMethoden (stellen Sie sicher, dass Sie sowohl GET als auch POST akzeptieren) und verwenden Sie das Attribut-Routing, um mit dem in Ihrem OAuth2-Autorisierungsserver definierten AuthorizeEndpointPath (dh [Route("oauth2/authorize")]in) übereinzustimmen mein Beispiel, in dem ich das geändert habe AuthorizeEndpointPath, um es oauth2/als Pfadbasis zu verwenden).

Zum anderen müssen Sie Ihrer Web-App einen OAuth2-Autorisierungsclient hinzufügen. Leider gibt es in Katana keinen generischen OAuth2-Client-Support, und Sie müssen Ihren eigenen erstellen. Ich habe dem Katana-Team persönlich einen Vorschlag unterbreitet, der jedoch abgelehnt wurde. Aber keine Panik, es ist ziemlich einfach:

Kopieren Sie die entsprechenden Dateien aus dem dort befindlichen Microsoft.Owin.Security.Google-Repository: https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs

Sie müssen GoogleOAuth2AuthenticationHandler, GoogleOAuth2AuthenticationMiddleware, GoogleOAuth2AuthenticationOptions, GoogleAuthenticationExtensions(Sie werden die ersten 2 Methoden entsprechend der Google OpenID Implementierung entfernen müssen), IGoogleOAuth2AuthenticationProvider, GoogleOAuth2ReturnEndpointContext, GoogleOAuth2AuthenticationProvider, GoogleOAuth2AuthenticatedContextund GoogleOAuth2ApplyRedirectContext. Wenn Sie diese Dateien in Ihr Projekthosting "webpics.com" eingefügt haben, benennen Sie sie entsprechend um und ändern Sie die URL der Autorisierungs- und Zugriffstoken-Endpunkte so, dass sie GoogleOAuth2AuthenticationHandlermit denen übereinstimmen, die Sie auf Ihrem OAuth2-Autorisierungsserver definiert haben.

Fügen Sie dann die Use-Methode aus Ihrem umbenannten / benutzerdefinierten GoogleAuthenticationExtensionsElement zu Ihrer OWIN-Startklasse hinzu. Ich empfehle die Verwendung, AuthenticationMode.Activedamit Ihre Benutzer direkt zu Ihrem API OAuth2-Autorisierungsendpunkt umgeleitet werden. Daher sollten Sie den Roundtrip "api.prettypictures.com/Account/ExternalLogins" unterdrücken und die OAuth2-Client-Middleware 401 Antworten ändern lassen, um die Clients auf Ihre API umzuleiten.

Viel Glück. Und zögern Sie nicht, wenn Sie weitere Informationen benötigen;)


Hallo, vielen Dank für Ihre Antwort, sie hat mich ziemlich in die richtigen Richtungen gelenkt und ich bin fast da. Ich habe meine eigene Middleware-Implementierung mit den Klassen erstellt, auf die Sie verwiesen haben. Was ich geklebt ist , wenn ich auf den Kunden ursprünglichen Umleitung zurück redirect_uri, zum Beispiel http://www.webpic.com/signin-prettypictures, was setze ich in die Query - String , so dass die Middleware - Protokolle weiß , was zu tun?
Joshcomley

(Ich habe versucht, den Status dort als
Abfragezeichenfolgenparameter einzufügen

Gut zu hören! Ich weiß nicht, ob Sie Ihr letztes Problem gelöst haben, aber ich stelle mir vor, dass das Festlegen von RedirectUri für die AuthenticationProperties, die an IAuthenticationManager.Challenge übergeben wurden, den Trick macht;)
Kévin Chalet

1
@ Mayabelle: Sicher, bitte sehen Sie meine Antwort hier: stackoverflow.com/questions/28487586/…
Kévin Chalet

1
@CularBytes Ich werde einen Blick auf Ihre andere "POST"
werfen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.