Web API Antiforgery Tokens are swapped

Viewed 2739

My Web APIs are accessed by Angular client hosted in Node process and hence I am generating anti forgery tokens as part of OAuth token generation and attach them as cookies for the response as shown below:

public static void SetXsrfCookies(IOwinResponse response, DateTime expiresUtc)
    {
        string cookieToken;
        string formToken;

        AntiForgery.GetTokens("", out cookieToken, out formToken);

        response.Cookies.Append(AntiForgeryConfig.CookieName, cookieToken,
            new CookieOptions()
            {
                HttpOnly = true /* we want JavaScript clients to read this cookie*/,
                Expires = expiresUtc
            });

        response.Cookies.Append("FORM-TOKEN", formToken,
            new CookieOptions()
            {
                HttpOnly = true /* we want JavaScript clients to read this cookie*/,
                Expires = expiresUtc
            });
    }

I see cookies being received by the client.

Then for subsequent calls, I include below headers:

Authorization: Bearer someOAuthToken
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36     (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Cache-Control: no-cache
__RequestVerificationToken: someCookieToken
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: Logout=true; __RequestVerificationToken=someFormToken

As can be noted, I am including both cookieToken and formToken in the headers.

When client makes the call, I validate those tokens as shown below (this code is as per other SO people discussions):

var headers = actionContext.Request.Headers;
var cookie = headers.GetCookies()
                    .Select(c => c[AntiForgeryConfig.CookieName])
                    .FirstOrDefault();
var aspNetMvcRequestVerificationToken = headers.GetValues(AntiForgeryConfig.CookieName).FirstOrDefault();
AntiForgery.Validate(cookie != null ? cookie.Value : null,  aspNetMvcRequestVerificationToken);

This method fails with the below error

"Validation of the provided anti-forgery token failed. The cookie "__RequestVerificationToken" and the form field "__RequestVerificationToken" were swapped."

After this, I have tried swapping but getting below error:

"The provided anti-forgery token was meant for a different claims-based user than the current user."

I have looked at few people reporting similar errors: link but not sure about the solution. Can someone review the above code and let me know the error.

Note: I have used Fiddler for testing purposes.

Thanks

3 Answers

I check your code, and find some problems.

  1. You set someCookieToken in the request header, and set someFormToken in the cookie, so you indeed swap the cookie token and form token by mistake. You should set someCookieToken in cookie, and set someFormToken in the request header.
  2. You use the method AntiForgery.GetTokens to create the cookie token and form token, and I only find the code that you add them into Cookies, but I can not find the code how you set __RequestVerificationToken into request header. So I think the cookie token and form token you added in the request is not a correct pair.

In your line of the code, "__RequestVerificationToken=someFormToken", change it to "RequestVerificationToken" or some other name. Since the Form token and cookie token both has the same name "__RequestVerificatioToken", you are getting the error.

Related