What is the XsrfKey used for and should I set the XsrfId to something else?

杀马特。学长 韩版系。学妹 提交于 2019-11-30 17:46:20

Take a look at ManageController methods LinkLogin and 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 });
    }

These are the methods that handle linking of external accounts (i.e. Google, Facebook, etc.). The flow goes like this:

  1. User clicks "Link Account" button, which calls a POST to LinkLogin method.
  2. LinkLogin returns ChallengeResult object, with callback url set to LinkLoginCallback method.
  3. ChallengeResult.ExecuteResult is called by MVC framework, calls IAuthenticationManager.Challenge, which causes a redirect to the specific external login provider (let's say: google).
  4. User authenticates with google, then google redirects to callback url.
  5. The callback is handled with LinkLoginCallback. Here, we want to prevent XSRF and verify that the call was initiated by a user, from a page served by our server (and not by some malicious site).

Normally, if it was a simple GET-POST sequence, you would add a hidden <input> field with an anti-forgery token and compare it with a corresponding cookie value (that's how Asp.Net Anti-Forgery Tokens work).

Here, the request comes from external auth provider (google in our example). So we need to give the anti-forgery token to google and google should include it in the callback request. That's exactly what state parameter in OAuth2 was designed for.

Back to our XsrfKey: everything you put in AuthenticationProperties.Dictionary will be serialized and included in the state parameter of OAuth2 request - and consequentially, OAuth2 callback. Now, GetExternalLoginInfoAsync(this IAuthenticationManager manager, string xsrfKey, string expectedValue) will look for the XsrfKey in the received state Dictionary and compare it to the expectedValue. It will return an ExternalLoginInfo only if the values are equal.

So, answering your original question: you can set XsrfKey to anything you want, as long as the same key is used when setting and reading it. It doesn't make much sense to set it to anything random - the state parameter is encrypted, so no one expect you will be able to read it anyway.

Just leave it as is:

As the name of the member states it is a key:

private const string XsrfKey = "XsrfId";

It is defined in this manner to avoid "magic numbers" and then is used a little down in the scaffold code:

public override void ExecuteResult(ControllerContext context)
{
    var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
    if (UserId != null)
    {
        properties.Dictionary[XsrfKey] = UserId;
    }
    context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}

The value of the dictionary item is then set to the UserId property in the above code by using the XsrfKey member as the key.

IOW the code is already setting the XSRF dictionary item to the value of the user ID in the snippet. If you change the XsrfKey members value to anything else you will cause problems down the line, since the expected key "XsrfId" will have no value set.

If by changing it to something more random you are implying to change the value and not they key of the dictionary, or in other words, not set it to the user id then please see the following for an explanation of the anti forgery token inner workings.

http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!