Date un'occhiata a ManageController
metodi LinkLogin
e LinkLoginCallback
:
//
// POST: /Manage/LinkLogin
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LinkLogin(string provider)
{
// Request a redirect to the external login provider to link a login for the current user
return new AccountController.ChallengeResult(provider, Url.Action("LinkLoginCallback", "Manage"), User.Identity.GetUserId());
}
//
// GET: /Manage/LinkLoginCallback
public async Task<ActionResult> LinkLoginCallback()
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
if (loginInfo == null)
{
return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
}
var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
return result.Succeeded ? RedirectToAction("ManageLogins") : RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
}
Questi sono i metodi che gestiscono collegano dei conti con l'estero (cioè Google, Facebook, ecc). Il flusso va così:
- L'utente fa clic sul pulsante "Collega account", che chiama un metodo da POST a
LinkLogin
.
LinkLogin
restituisce ChallengeResult
oggetto, con url di richiamata impostato su LinkLoginCallback
metodo.
ChallengeResult.ExecuteResult
viene chiamato da MVC framework, chiama IAuthenticationManager.Challenge
, che provoca un reindirizzamento al provider di accesso esterno specifico (diciamo: google).
- L'utente si autentica con google, quindi reindirizzamenti di Google a url di richiamata.
- Il callback viene gestito con
LinkLoginCallback
. Qui, vogliamo impedire XSRF e verificare che la chiamata sia stata avviata da un utente, da una pagina servita dal nostro server (e non da un sito malevolo).
Normalmente, se si trattava di una semplice sequenza di GET-POST, si dovrebbe aggiungere un nascosta <input>
campo con un token anti-contraffazione e confrontarla con un corrispondente valore del cookie (che è come Asp.Net Anti-Forgery Tokens di lavoro).
Qui, la richiesta proviene da un provider di autenticazione esterno (google nel nostro esempio). Quindi dobbiamo dare il token anti-contraffazione a google e google dovrebbe includerlo nella richiesta di callback. Questo è esattamente ciò per cui è stato progettato state parameter in OAuth2.
Torniamo al nostro XsrfKey
: tutto ciò che si mette in AuthenticationProperties.Dictionary
verrà serializzato e inclusi nel parametro state
di richiesta OAuth2 - e di conseguenza, OAuth2 callback. Ora, GetExternalLoginInfoAsync(this IAuthenticationManager manager, string xsrfKey, string expectedValue)
cercherà lo XsrfKey
nel dizionario di stato ricevuto e lo confronterà con lo expectedValue
. Restituirà un valore ExternalLoginInfo
solo se i valori sono uguali.
Quindi, rispondendo alla domanda originale: è possibile impostare XsrfKey
su tutto ciò che si desidera, purché venga utilizzato lo stesso tasto durante l'impostazione e la lettura. Non ha molto senso impostarlo su qualcosa di casuale: il parametro state
è crittografato, quindi nessuno si aspetta che tu possa leggerlo comunque.
Grazie. Continuo a pensare che sia una buona idea cambiarlo in qualcosa di diverso dalla chiave originale che arriva in un nuovo progetto, quindi non sarà immaginabile nel caso qualcuno provasse a ricrearlo – Yovav