2015-06-03 27 views
8

Próbuję zrozumieć, jak działa OAuth, ale czuję się jak jeden wielki program magiczny i nie podoba mi się to.W jaki sposób OAuth z OWIN działa w MVC5?

Utworzono nowy projekt MVC5 i włączono autoryzację facebook. To wszystko działa dobrze, jednak staram się zrozumieć, jak to działa.

Oto część, w której się gubię. Wyobraź sobie, że użytkownik chce się zalogować po raz pierwszy. Ta metoda jest wykonywana:

public async Task<ActionResult> ExternalLoginCallback(string returnUrl) 
    { 
     var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); 
     if (loginInfo == null) 
     { 
      return RedirectToAction("Login"); 
     } 

     // Sign in the user with this external login provider if the user already has a login 
     var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false); 
     switch (result) 
     { 
      case SignInStatus.Success: 
       return RedirectToLocal(returnUrl); 
      case SignInStatus.LockedOut: 
       return View("Lockout"); 
      case SignInStatus.RequiresVerification: 
       return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false }); 
      case SignInStatus.Failure: 
      default: 
       // If the user does not have an account, then prompt the user to create an account 
       ViewBag.ReturnUrl = returnUrl; 
       ViewBag.LoginProvider = loginInfo.Login.LoginProvider; 
       return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); 
     } 
    } 

Ten kod wyświetla stronę logowania FB, a FB zajmie się danymi uwierzytelniającymi. Wszystko działa dobrze. Ale potem ta linia jest wykonywana: var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);. W ustawieniu loginInfo widzę, że nazwa jest ustawiona, ale zmienna result jest ustawiona na Failure. Dlaczego? Użytkownik został właśnie uwierzytelniony przez FB, więc dlaczego jest wartość false?

Ale potem, ku mojemu odczuciu, robi się dziwniej. Gdy kontynuuję uruchamianie przykładowej aplikacji, prosi o podanie adresu e-mail. Podaję adres e-mail i voila, jestem zalogowany. Odkąd badam cały ten login, wylogowuję się i chcę się zalogować ponownie. Dlatego wylogowuję się i od razu loguję ponownie za pomocą FB. I tu właśnie uderzam głową o ścianę. Kiedy kod ponownie uderzy w tę linię: var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);, wynik zostanie ustawiony na true !!

Czy ktoś mógłby mi wyjaśnić, co się tutaj dzieje?

Odpowiedz

5

Gdy używasz zewnętrznego logowania, SignInManager sprawdza dane uwierzytelniające użytkownika na stronie zewnętrznej (w tym przypadku na Facebooku). Jeśli strona zewnętrzna pomyślnie sprawdziła poświadczenia, SignInManager sprawdza, czy istnieje rekord użytkownika. Ponieważ to pierwsze logowanie, nie ma żadnego dostępnego rekordu użytkownika. Ta część zajmuje się tym:

case SignInStatus.Failure: 
     default: 
      // If the user does not have an account, then prompt the user to create an account 
      ViewBag.ReturnUrl = returnUrl; 
      ViewBag.LoginProvider = loginInfo.Login.LoginProvider; 
      return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); 

Pozwala to na użycie innego adresu e-mail. Najczęściej jest używanie tego samego adresu e-mail!

Niektóre próbki: http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on.

+1

Dzięki. Gdzie mogę znaleźć część, w której SignInManager sprawdza, czy obecny jest rekord? To wydaje się magiczne. – Martijn

+2

Znalezione na tej stronie: https://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.Owin/2.2.0-alpha1-140725/Release/Default/Microsoft.AspNet.Identity .Owin/Microsoft.AspNet.Identity.Owin/SignInManager.cs? ImageName = Microsoft.AspNet.Identity.Owin. –

+1

Tak, po zapoznaniu się ze źródłem, wierzę, że SignInStatus.Failure ma nazwę tylko mylić. Podczas wywoływania SignInManager.ExternalSignInAsync(), uważam, że można go zwrócić tylko dla nieznalezionego użytkownika. Może on zostać zwrócony w przypadku innych typów awarii w innych połączeniach. – mheyman