asp.net-mvc-5 login - ASP.NET MVC5 OWIN Facebook-Authentifizierung funktioniert plötzlich nicht




authentication database (11)

Ich arbeite seit drei Tagen an einer Lösung. Und ich habe es gerade auf github gefunden ( https://github.com/aspnet/AspNetKatana/issues/38#issuecomment-290400987 )

var facebookOptions = new FacebookAuthenticationOptions()
{
    AppId = "xxxxx",
    AppSecret = "xxxxx",
};

// Set requested scope
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("public_profile");

// Set requested fields
facebookOptions.Fields.Add("email");
facebookOptions.Fields.Add("first_name");
facebookOptions.Fields.Add("last_name");

facebookOptions.Provider = new FacebookAuthenticationProvider()
{
    OnAuthenticated = (context) =>
        {
            // Attach the access token if you need it later on for calls on behalf of the user
            context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));

            foreach (var claim in context.User)
            {
                //var claimType = string.Format("urn:facebook:{0}", claim.Key);
                var claimType = string.Format("{0}", claim.Key);
                string claimValue = claim.Value.ToString();

                    if (!context.Identity.HasClaim(claimType, claimValue))
                        context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
            }

            return Task.FromResult(0);
       }
};

app.UseFacebookAuthentication(facebookOptions);

Und um Werte zu bekommen

var info = await AuthenticationManager.GetExternalLoginInfoAsync();

if (info != null)
{
    var firstName = info.ExternalIdentity.Claims.First(c => c.Type == "first_name").Value;
    var lastName = info.ExternalIdentity.Claims.First(c => c.Type == "last_name").Value;
}

Update 2017!

Das Problem, das ich hatte, als ich die ursprüngliche Frage gepostet habe, hat nichts mit den letzten Änderungen zu tun, die Facebook gemacht hat, als sie alle zur Version 2.3 ihrer API gezwungen haben. Eine Lösung für dieses spezielle Problem finden Sie in der Antwort von sammy34 . In Version 2.3 des Endpunkts / oauth / access_token wird jetzt JSON anstelle von formcodierten Werten zurückgegeben

Aus historischen Gründen, hier ist meine ursprüngliche Frage / Problem:

Ich habe eine MVC5-Webanwendung, die die integrierte Unterstützung für die Authentifizierung über Facebook und Google verwendet. Als wir diese App vor ein paar Monaten erstellten, folgten wir diesem Tutorial: http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on und alles hat gut funktioniert.

Jetzt hat die Facebook-Authentifizierung plötzlich aufgehört zu arbeiten. Die Google-Authentifizierung funktioniert immer noch gut.

Beschreibung des Problems: Wir klicken auf den Link, um eine Verbindung über Facebook herzustellen, wir werden zu Facebook weitergeleitet, wo wir gefragt werden, ob wir unserer Facebook-App Zugriff auf unser Profil gewähren möchten. Wenn wir auf "OK" klicken, werden wir zurück auf unsere Seite geleitet, aber anstatt eingeloggt zu sein, landen wir einfach auf dem Login-Bildschirm.

Ich habe diesen Prozess im Debug-Modus durchlaufen und ich habe dieses ActionResult in meinem Account-Controller gemäß dem oben genannten Tutorial:

// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }
    ............

Beim Durchlaufen des Codes und bei der Rückkehr von Facebook ist das loginInfo-Objekt immer NULL, wodurch der Benutzer zurück zum Login geleitet wird.

Um zu verstehen, was tatsächlich hinter den Kulissen passiert, habe ich Fiddler installiert und den HTTP-Verkehr überwacht. Was ich entdeckt habe, ist, dass Facebook mit einem Klick auf "OK" im Facebook-Erlaubnisdialog zurück zu unserer Anwendung mit dieser URL umleitet:

https://localhost/signin-facebook?code=<access-token>

Diese URL ist keine tatsächliche Datei und wird wahrscheinlich von einem Controller / Handler verarbeitet, der in dieses OWIN-Framework eingebaut ist. Am wahrscheinlichsten ist es eine Verbindung zurück zu Facebook unter Verwendung des gegebenen Codes, um Informationen über den Benutzer abzufragen, der sich anzumelden versucht. Nun, das Problem ist, dass wir statt dessen:

/Account/ExternalLoginCallback?error=access_denied

Ich bin sicher, dass Facebook etwas tut, das heißt, anstatt uns die Benutzerdaten zu geben, leitet es uns mit dieser Fehlermeldung zurück.

Dies verursacht den AuthenticationManager.GetExternalLoginInfoAsync(); fehlschlagen und immer NULL zurückgeben.

Ich habe keine Ideen mehr. Soweit wir wissen, haben wir an unserem Ende nichts geändert.

Ich habe versucht, eine neue Facebook-App zu erstellen, ich habe versucht, das Tutorial wieder zu folgen, aber ich habe immer das gleiche Problem.

Irgendwelche Ideen willkommen!

Aktualisieren!

OK, das macht mich wahnsinnig! Ich habe jetzt die erforderlichen Schritte manuell ausgeführt, um die Authentifizierung durchzuführen, und alles funktioniert gut, wenn ich das tue. Warum in aller Welt funktioniert das nicht, wenn MVC5 Owin benutzt wird?

Das habe ich gemacht:

    // Step 1 - Pasted this into a browser, this returns a code
    https://www.facebook.com/dialog/oauth?response_type=code&client_id=619359858118523&redirect_uri=https%3A%2F%2Flocalhost%2Fsignin-facebook&scope=&state=u9R1m4iRI6Td4yACEgO99ETQw9NAos06bZWilJxJrXRn1rh4KEQhfuEVAq52UPnUif-lEHgayyWrsrdlW6t3ghLD8iFGX5S2iUBHotyTqCCQ9lx2Nl091pHPIw1N0JV23sc4wYfOs2YU5smyw9MGhcEuinvTAEql2QhBowR62FfU6PY4lA6m8pD3odI5MwBYOMor3eMLu2qnpEk0GekbtTVWgQnKnH6t1UcC6KcNXYY

I was redirected back to localhost (which I had shut down at this point to avoid being redirected immediately away).  The URL I was redirected to is this:

https://localhost/signin-facebook?code=<code-received-removed-for-obvious-reasons>

Now, I grabbed the code I got and used it in the URL below:

// Step 2 - opened this URL in a browser, and successfully retrieved an access token
https://graph.facebook.com/oauth/access_token?client_id=619359858118523&redirect_uri=https://localhost/signin-facebook&client_secret=<client-secret>&code=<code-from-step-1>

// Step 3 - Now I'm able to query the facebook graph using the access token from step 2!

https://graph.facebook.com/me?access_token=<access-token-from-step-2>

Keine Fehler, alles funktioniert super! Warum, zum Teufel, funktioniert das nicht, wenn man das MVC5 Owin-Zeug benutzt? Es ist offensichtlich etwas falsch mit der OWin-Implementierung.


Ok, ich habe eine Lösung für das Problem.

Dies ist der Code, den ich zuvor in meiner Startup.Auth.cs-Datei hatte:

var x = new FacebookAuthenticationOptions();
            //x.Scope.Add("email");
            x.AppId = "1442725269277224";
            x.AppSecret = "<secret>";
            x.Provider = new FacebookAuthenticationProvider()
            {
                OnAuthenticated = async context =>
                {
                        //Get the access token from FB and store it in the database and
                    //use FacebookC# SDK to get more information about the user
                    context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken",context.AccessToken));
                    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:name", context.Name));
                    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:email", context.Email));
                }
            };
            x.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
            app.UseFacebookAuthentication(x);

Beachten Sie, wie die

x.Scope.Add("email")

Zeile wurde auskommentiert, aber ich frage später noch nach der E-Mail im OnAuthenticated-Handler? Ja, das ist richtig. Aus irgendeinem Grund funktionierte das einige Wochen lang einwandfrei.

Meine Lösung war, das x.scope.Add ("email") einfach auskommentieren; Zeile, um sicherzustellen, dass die Variable scope = email in der ersten Anfrage an Facebook vorhanden war.

Jetzt funktioniert alles wie es ist!

Ich kann nicht verstehen, warum das früher so funktioniert hat, wie es war. Die einzige Erklärung, die ich finden kann, ist, dass Facebook etwas an ihrem Ende verändert hat.



Ich hatte dieses Problem auch, aber es wurde nicht durch die Einstellung des Bereichs verursacht. Ich habe lange gebraucht, um das herauszufinden, aber was mich schließlich ansprach, war, einen benutzerdefinierten Logger einzurichten, indem ich Folgendes in OwinStartup.Configuration(IAppBuilder app) .

app.SetLoggerFactory(new LoggerFactory()); 
// Note: LoggerFactory is my own custom ILoggerFactory

Dies gab folgendes aus:

2014-05-31 21: 14: 48,508 [8] FEHLER
Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware
[(null)] - 0x00000000 - Authentifizierung fehlgeschlagen
System.Net.Http.HttpRequestException: Beim Senden der Anforderung ist ein Fehler aufgetreten. ---> System.Net.WebException: Der entfernte Name konnte nicht
gelöst werden: "graph.facebook.com" unter
System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback (IAsyncResultar) --- Ende der inneren Ausnahme Stack-Trace --- at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (Task
Aufgabe) um
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Aufgabenaufgabe) unter System.Runtime.CompilerServices.TaskAwaiter`1.GetResult () at
Microsoft.Owin.Security.Facebook.FacebookAuthenticationHandler.d__0.MoveNext ()

Basierend auf dem obigen Aufruf-Stack habe ich festgestellt, dass meine Azure-VM graph.facebook.com nicht auflösen konnte. Alles, was ich tun musste, um das zu beheben, war "ipconfig / registerdns" auszuführen und ich war alles behoben ...


Stellen Sie sicher, dass Sie eine externe Internetverbindung von Ihrer Anwendung erhalten. Wenn nicht, reparieren Sie Ihre externe Internetverbindung. Mein Problem war, dass ich eine EC2 AWS-Instanz verwendete, die plötzlich aufhörte, sich mit dem Internet zu verbinden. Es dauerte eine Weile, bis ich erkannte, dass das das Problem war.


Habe dieses Problem gestern bemerkt. Facebook unterstützt Microsoft.Owin.Security.Facebook Version 3.0.1 nicht mehr. Für mich funktionierte es, Version 3.1.0 zu installieren. Um auf 3.1.0 zu aktualisieren, führen Sie den Befehl Install-Package Microsoft.Owin.Security.Facebook in der Package Manager-Konsole aus: https://www.nuget.org/packages/Microsoft.Owin.Security.Facebook


Das letzte Facebook Upgrade war am 2015-02-09 ( https://www.nuget.org/packages/Microsoft.AspNet.WebPages.OAuth/ )

Die neueste Version der API war zu diesem Zeitpunkt Version 2.2. Die Version 2.2 ist am 25. März 2017 abgelaufen, als das Problem anfing. ( https://developers.facebook.com/docs/apps/changelog )

Ich vermute, Facebook hat wahrscheinlich die API automatisch aktualisiert und jetzt kann die MS OAUTH-Bibliothek die neue Antwort nicht analysieren.

tldr: Die OAuth-Bibliothek von Microsoft WebPages ist veraltet (zumindest für FB), und Sie müssen wahrscheinlich eine andere Lösung finden


Das hat mich verrückt gemacht. Alles funktionierte, bis ich in meiner Staging-Umgebung bereitgestellt wurde. Ich verwendete Microsoft.Owin.Security.Facebook Version 3.0.1 von Nuget. Es wurde auf die Prelease-Version 3.1.0 von Nuget aktualisiert und ich habe nicht mehr den Fehler "Zugriff verweigert" erhalten ...


Ich hatte dieses Problem auch. Ich habe viele Artikel und Themen für zwei Tage darunter gelesen. Keiner von ihnen arbeitete für mich. Der Facebook-Login hatte vor der Bereitstellung einwandfrei funktioniert, aber danach nicht. Ich habe herausgefunden, dass etwas mit meiner VPS-Internetverbindung nicht stimmt, also habe ich NextVPN auf meinem VPS versucht. Aber als ich versuchte, mich über meinen Computer anzumelden, gab es keine neue Verbindung in NextVPNs internem ProxiFire. Schließlich hat die Installation von OpenVPN auf meinem VPS das Problem gelöst.


Die obigen Lösungen haben bei mir nicht funktioniert. Am Ende schien es mit der Sitzung zu tun zu haben. Wenn Sie die Sitzung im vorherigen Aufruf "aufwachen", wird von GetExternalLoginInfoAsync () nicht mehr null zurückgegeben.

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
        Session["WAKEUP"] = "NOW!";
        // Request a redirect to the external login provider
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }

Wie das OP hatte ich die 3rd Party Auth für eine lange Zeit gut funktioniert dann plötzlich hörte es auf. Ich glaube, es war aufgrund der Änderungen in meinem Code vorgenommen, wenn ich die Sitzung einrichten, um Redis Cache auf Azure zu verwenden.


Aktualisieren Sie das MVC-Projekt

Verwenden Sie Nuget , um die neueste Web-API zu erhalten.

Projekt - Rechtsklick - Nuget-Pakete verwalten - Nach Web-API (Microsoft ASP.NET-Web-API ...) suchen und in Ihrem MVC-Projekt installieren.

Dann müssen Sie noch Web-API-Routing zum funktionieren bringen. Von Microsoft Konfigurieren von ASP.NET Web API 2

Fügen Sie WebApiConfig.cs dem App_Start / -Ordner hinzu

using System.Web.Http;

namespace WebApplication1
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // TODO: Add any additional configuration code.

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

        // WebAPI when dealing with JSON & JavaScript!
        // Setup json serialization to serialize classes to camel (std. Json format)
        var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
        formatter.SerializerSettings.ContractResolver =
            new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
        }
    }
}

Wenn Sie ein MVC-Projekt haben, wird es Global.asax.cs haben , fügen Sie die neuen Routen hinzu. Reihenfolge der Global.asax.cs-Routen ist kritisch. Beachten Sie, dass es veraltete Beispiele gibt, die WebApiConfig.Register

Fügen Sie diese Zeile zu Global.asax.cs hinzu: GlobalConfiguration.Configure(WebApiConfig.Register);

protected void Application_Start()
{
    // Default stuff
    AreaRegistration.RegisterAllAreas();

    // Manually installed WebAPI 2.2 after making an MVC project.
    GlobalConfiguration.Configure(WebApiConfig.Register); // NEW way
    //WebApiConfig.Register(GlobalConfiguration.Configuration); // DEPRECATED

    // Default stuff
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

WebAPI-Hilfe

Installieren Sie WebAPI.HelpPage, um die ( sehr ) hilfreichen WebAPI-Hilfeseiten zu erhalten. Siehe http://channel9.msdn.com/Events/Build/2014/3-644 (~ 42 Minuten in) für das, was es tut. Es sieht sehr hilfreich aus!

Nuget-Konsole: Install-Package Microsoft.AspNet.WebApi.HelpPage

Um zu überprüfen, ob WebAPI funktioniert:

Zum Controller-Ordner -> Neues Objekt hinzufügen -> Web-API-Controller-Klasse.

public class TestController : ApiController
{
    //public TestController() { }

    // GET api/<controller>
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }
    //...
}

Jetzt können Sie wie gewohnt in IE / FF / Chrome oder in den JavaScript-Konsolen für Nicht-Get-Tests testen.

(Wenn nur der Controller in der URL die Aktion GET () im neuen Web-API-Controller aufruft, wird er je nach REST automatisch den Methoden / Aktionen zugeordnet, zB PUT / POST / GET / DELETE, Sie müssen ihn nicht aufrufen sie durch Aktion wie in MVC) Die URL direkt:

http://localhost:PORT/api/CONTROLLERNAME/

Verwenden Sie alternativ jQuery, um den Controller abzufragen. Führen Sie das Projekt aus, öffnen Sie die Konsole (F12 in IE) und versuchen Sie, eine Ajax-Abfrage auszuführen. (Überprüfen Sie Ihren PORT & CONTROLLERNAME)

$.get( "http://localhost:PORT/api/CONTROLLERNAME/", function( data ) {
    //$( ".result" ).html( data );
    alert( "Get data received:" + data);
});

Randnotiz: Bei der Kombination von MVC und Web-API in einem Projekt sind einige Vor- und Nachteile zu beachten

Überprüfung der WebAPI-Hilfe: http://localhost:PORT/help





facebook asp.net-mvc-5 owin