2015-06-03 32 views
8

Sto cercando di capire come funziona OAuth, ma sembra un grande spettacolo di magia, e non mi piace.Come funziona OAuth con OWIN in MVC5?

Ho creato un nuovo progetto MVC5 e abilitato l'autenticazione di Facebook. Tutto funziona perfettamente, tuttavia, sto cercando di capire come funziona.

Questa è la parte in cui mi perdo. Immagina che un utente voglia accedere per la prima volta. Questo metodo è l'esecuzione:

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 }); 
     } 
    } 

Questo codice mostra la pagina di login FB e FB si prenderà cura delle credenziali. Tutto funziona bene. Ma poi, questa riga viene eseguita: var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);. Riesco a vedere in loginInfo che è stato impostato un nome, ma il variabile result è impostato su Failure. Perché? L'utente è stato appena autenticato da FB, quindi perché il valore è false?

Ma poi, per il mio sentimento diventa più strano. Quando continuo a eseguire l'applicazione di esempio, mi chiede di inserire un indirizzo e-mail. Inserisco un indirizzo e-mail e voilà, ho effettuato l'accesso. Poiché sto esplorando l'intera questione di accesso, mi disconnetto e voglio accedere di nuovo. Quindi, mi disconnetto e ricomincio immediatamente utilizzando FB. E qui è dove sbatto la testa contro il muro. Quando il codice raggiunge nuovamente questa riga: var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false); il risultato è impostato su true !!

Qualcuno potrebbe spiegarmi cosa sta succedendo qui?

risposta

5

Quando si utilizza l'accesso esterno, SignInManager convalida le credenziali dell'utente con la parte esterna (in questo caso Facebook). Se la parte esterna ha convalidato correttamente le credenziali, SignInManager controlla se è presente un record utente. Dato che questo è il tuo primo accesso, non c'è nessun record utente disponibile. Questa parte si occupa di questo:

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 }); 

Ciò consente di utilizzare un altro indirizzo di posta elettronica. Molto comune è usare lo stesso indirizzo email!

Alcuni campioni: http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on.

+1

Grazie. Dove posso trovare la parte in cui SignInManager controlla se è presente un record? Questo sembra una specie di magico. – Martijn

+2

Trovato in questo sito Web: 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

Sì, dopo aver guardato la fonte, credo che SignInStatus.Failure sia chiamato solo per confondere. Nel chiamare SignInManager.ExternalSignInAsync(), credo che possa essere restituito solo per un utente non trovato. Può essere restituito per altri tipi di guasti in altre chiamate. – mheyman