4

I am trying to post a payload to our backend system from my UWP app. For which I am first doing a GET to fetch the CSRF token and then adding that to the header of the POST request. While posting, I am still getting the 403 Forbidden error.

I am cross-testing this with 'Insomnia' REST client by doing a separate GET and POST requests and feeding the CSRF token fetched from the GET to the POST header and it is working just fine.

Getting the token:

public async Task<string> GetCSRF()
{
    using (HttpClient httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(
            System.Text.Encoding.ASCII.GetBytes(
                    string.Format("{0}:{1}", userName.Text.ToUpper(), SAPpassword.Password))));

        httpClient.DefaultRequestHeaders.Add("X-CSRF-TOKEN", "fetch");
        HttpResponseMessage response = await httpClient.GetAsync(new Uri(_URI));
        response.EnsureSuccessStatusCode();
        if (response.Content == null)
            return null;
        String csrfToken = response.Headers.GetValues("X-CSRF-TOKEN").FirstOrDefault();
        return csrfToken;
    }
}

I received the following header back with the csrf token:

response.Headers
{
    x-csrf-token: w1Id2Kn1r0d6EItk6vEi0g==
    cache-control: no-store, no-cache
    sap-metadata-last-modified: Fri, 01 Sep 2017 10:57:07 GMT
    dataserviceversion: 2.0
    set-cookie: sap-usercontext=sap-client=100; path=/, MYSAPSSO2=AjQxMDMBABhTAFMARQBOAEcAVQBQAFQAQQAgACAAIAACAAYxADAAMAADABBHAFcAMQAgACAAIAAgACAABAAYMgAwADEANwAwADkAMAAxADIAMAA0ADkABQAEAAAACAYAAlgACQACRQD%2fAPswgfgGCSqGSIb3DQEHAqCB6jCB5wIBATELMAkGBSsOAwIaBQAwCwYJKoZIhvcNAQcBMYHHMIHEAgEBMBkwDjEMMAoGA1UEAxMDR1cxAgcgFAMoIAMBMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNzA5MDEyMDQ5MzhaMCMGCSqGSIb3DQEJBDEWBBRP7sl8St9p53T9Sfu58sTb3jTNFjAJBgcqhkjOOAQDBC8wLQIVALIiQKECoPjhBihxA7OXoDOEGy3YAhQroXwahnTKR0A7du7u5zwj1Q0cgg%3d%3d; path=/; domain=.mindsetconsulting.com, SAP_SESSIONID_GW1_100=u1BKLug0BNWYM0-zg_JWTBEihxmPVxHnvTMKDkBCwEk%3d; path=/
    access-control-allow-credentials: true
    access-control-allow-headers: *
    access-control-allow-origin: *.google.com
    access-control-allow-methods: *
} System.Net.Http.Headers.HttpResponseHeaders

Posting payload with the token:

public async Task<string> SendChannelToSAP(UserStorage userStorage, string csrf)
{
    string payloadJson;
    string jsonResponse;
    HttpResponseMessage response;
    HttpContent content;

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
            "Basic", Convert.ToBase64String(
                System.Text.Encoding.ASCII.GetBytes(
                     string.Format("{0}:{1}", userName.Text.ToUpper(), SAPpassword.Password))));

        payloadJson = JsonConvert.SerializeObject(userStorage);
        content     = new StringContent(payloadJson);
        content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        client.DefaultRequestHeaders.Add("x-csrf-token", csrf);
        try
        {
            response = await client.PostAsync(_URI, content);
            if (response.IsSuccessStatusCode)
            {
                jsonResponse = await response.Content.ReadAsStringAsync();
                return jsonResponse;
                //do something with json response here                    
            }
            else
            {
                return null;
            }

        }
        catch (Exception e)
        {
            string error = e.GetBaseException().ToString();
            //Could not connect to server
            return null;
        }
    }
}

I am getting the following response

>response   
{
    StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
    {
      x-csrf-token: Required
      set-cookie: sap-usercontext=sap-client=100; path=/
      set-cookie: MYSAPSSO2=AjQxMDMBABhTAFMARQBOAEcAVQBQAFQAQQAgACAAIAACAAYxADAAMAADABBHAFcAMQAgACAAIAAgACAABAAYMgAwADEANwAwADkAMAAxADIAMAAzADgABQAEAAAACAYAAlgACQACRQD%2fAPswgfgGCSqGSIb3DQEHAqCB6jCB5wIBATELMAkGBSsOAwIaBQAwCwYJKoZIhvcNAQcBMYHHMIHEAgEBMBkwDjEMMAoGA1UEAxMDR1cxAgcgFAMoIAMBMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNzA5MDEyMDM4MTBaMCMGCSqGSIb3DQEJBDEWBBRSJQHrlPcSnxYjzSrqJ%2frOgo%2fg2TAJBgcqhkjOOAQDBC8wLQIUXjXws4bw63uLdWR%21NB9r9XUCD54CFQCH6y91A%21uKMzyfZEo7pvxjXys6zg%3d%3d; path=/; domain=.mindsetconsulting.com
      set-cookie: SAP_SESSIONID_GW1_100=Zvfe5ueHO1md7_ybPcLEcnem3m6PVRHnvP4KDkBCwEk%3d; path=/
      access-control-allow-credentials: true
      access-control-allow-headers: *
      access-control-allow-origin: *.google.com
      access-control-allow-methods: *
      content-length: 28
      content-type: text/plain; charset=utf-8
    }
} System.Net.Http.HttpResponseMessage
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Shinjan
  • 131
  • 1
  • 6
  • What type is `_URI` (POST call) and would you check that the HTTP `POST` verb is accepted on the server side for the *exact* URI you are calling? – Quality Catalyst Sep 01 '17 at 22:09
  • _URI is a string literal. The POST is working through postMan client. So I don't think thats an issue. – Shinjan Sep 01 '17 at 23:10
  • 1
    Are you sure you are not missing any other required headers? Maybe the content type you are using in postman is different. You are connecting to the site if you are getting back a 403 forbidden. You are just not authenticating properly. Other question is are testing connecting with postman from the same computer? Just want to eliminate the possibility of an IP restriction giving you the forbidden – Ken Tucker Sep 03 '17 at 15:05

1 Answers1

6

I found the issue. I had to collect the cookies along with the csrf token and apply those cookies in the actual POST method. That worked.

Getting the cookies after the GET

var uri = new Uri(_URI);
_responseCookies = cookies.GetCookies(uri).Cast<Cookie>();

And then adding the cookies to the POST

var cookieContainer = new CookieContainer();
foreach (var cookie in _responseCookies)
{
    cookieContainer.Add(new Uri(_URI), cookie);
}
var handler = new HttpClientHandler() { CookieContainer = cookieContainer };
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Shinjan
  • 131
  • 1
  • 6
  • You can accept your own answer if this solves your problem. Helps with anyone else coming across this in the future. – lee-m Aug 24 '22 at 13:04