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:
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!
quelle
Antworten:
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
OAuthAuthorizationServerMiddleware
OWIN Startup-Klasse anzuschließen . Sie finden es imMicrosoft.Owin.Security.OAuth
Nuget-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
AuthorizationController
Controller und Ihre eigenenAuthorize
Methoden (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 habeAuthorizeEndpointPath
, um esoauth2/
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
,GoogleOAuth2AuthenticatedContext
undGoogleOAuth2ApplyRedirectContext
. 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 sieGoogleOAuth2AuthenticationHandler
mit denen übereinstimmen, die Sie auf Ihrem OAuth2-Autorisierungsserver definiert haben.Fügen Sie dann die Use-Methode aus Ihrem umbenannten / benutzerdefinierten
GoogleAuthenticationExtensions
Element zu Ihrer OWIN-Startklasse hinzu. Ich empfehle die Verwendung,AuthenticationMode.Active
damit 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;)
quelle
redirect_uri
, zum Beispielhttp://www.webpic.com/signin-prettypictures
, was setze ich in die Query - String , so dass die Middleware - Protokolle weiß , was zu tun?