cancel
Showing results for 
Search instead for 
Did you mean: 

SAP Gateway - C#.NET HTTP WebRequest Post - "The remote server returned an error: (403) Forbidden."

Former Member
0 Kudos

Greetings All

We are trying to make a POST/PUT request from C# .NET 3.5 client application to SAP Netweaver Gateway;

Background:

  • The URL and port numbers are valid - this has been tested using Netweaver client and returns HTTP 200.
  • The code we have is able to obtain X-CSRF-Token and Cookie from an initial GET requestion, We add these relevant headers X-CSRF-Token  and  Set-cookie for the POST request.
  • We supply the correct UID and Password accordingly because we are able to obtain the token and cookie from previous get function.
  • SAP Netweaver version: 7.40 sp level 9

- Are there any other additional http request parameters required to succesfuly submit a POST or a PUT to SAP Netweaver Gateway.

- Are there any other additional settings from a transaction level that we have to set up to make this service call from external client source.

Please see the following code:

private void CheckCrossSiteForgeryToken()
        {
            Cursor.Current = Cursors.WaitCursor;

            string _UrlToInvoke= "https://xxxxxxxxxxx:4430/sap/opu/odata/SAP/ZTEST_PROJECT_SRV_01/ZTEST_PROJECTSet";

            HttpWebResponse httpWebResponse = null;

            try
            {

                HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(UrlToInvoke);

                httpRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
                httpRequest.Method = "GET";
                httpRequest.KeepAlive = true;
                httpRequest.ContentType = "application/x-www-form-urlencoded";
                httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";

                httpRequest.AllowAutoRedirect = true;
                httpRequest.Credentials = new NetworkCredential(txtUID.Text, txtpwd.Text);

                httpRequest.KeepAlive = true;
                httpRequest.Headers.Add("X-CSRF-Token", "Fetch");

                HttpWebResponse resp = (HttpWebResponse)httpRequest.GetResponse();

                // Assign values from response to class variables. 
                gcsrfToken = resp.Headers.Get("X-CSRF-Token");
                gsetCookie = resp.Headers.Get("Set-Cookie");

                Stream responseStream = resp.GetResponseStream();

               
            }
            catch (WebException error)
            {
                rtOutput.Text = "Error encountered: " + error.ToString();
            }

            Cursor.Current = Cursors.Default;

        }

    

The above function authenticates the user and pwd succesfully and returns the relevant Token and Cookie, with no issues..!

        private void PostDataTOSAPGateway()
        {
            Cursor.Current = Cursors.WaitCursor;

            string _UnloadReportEventURL1 = "https://xxxxxxxxxxx:4430/sap/opu/odata/SAP/ZTEST_PROJECT_SRV_01/ZTEST_PROJECTSet";
         

            HttpWebResponse httpWebResponse = null;

            try
            {

                HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(UrlToInvoke);

                httpRequest.Accept = "application/xml,application/atom+xml";
                httpRequest.Method = "PUT";
                httpRequest.ProtocolVersion = HttpVersion.Version11;
                httpRequest.AllowWriteStreamBuffering = true;

                httpRequest.KeepAlive = true;
                //httpRequest.ContentType = "application/x-www-form-urlencoded";

                //request.ContentType = "application/json; charset=utf-8";
                httpRequest.ContentType = "application/atom+xml";
                httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";//"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Mobile/7D11";
                httpRequest.AllowAutoRedirect = true;
                httpRequest.Credentials = new NetworkCredential(txtUID.Text, txtpwd.Text);

                httpRequest.KeepAlive = true;

           

               //set the Token
               httpRequest.Headers.Add("X-CSRF-Token", gcsrfToken);


                //set the cookie
               httpRequest.Headers.Add("Set-Cookie", gsetCookie);


                //check the header is applied before sending
               gcsrfToken = httpRequest.Headers.Get("X-CSRF-Token");


                String fileName = "Test XML.txt";

                //String fileName = "Event_single.txt";

                string sDir = "C:\\TestData\\";

                // Read the data.
                StreamReader streamData = new StreamReader(sDir + fileName); //StreamReader(Application.StartupPath + @"/Resources/" + fileName + ".txt"))

                //obtain the data to submit
                String sxml = streamData.ReadToEnd();

                streamData.Close();
                streamData.Dispose();

                byte[] bytedata = Encoding.UTF8.GetBytes(sxml);

                httpRequest.ContentLength = bytedata.Length;

                using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
                {
                    streamWriter.Write(sxml);
                    streamWriter.Flush();
                }

The HTTP Web exception occurs when we try to obtain the response from the above PUT the following:

the exception is HTTP 403.

                try
                {
                    httpWebResponse = (HttpWebResponse)httpRequest.GetResponse();
                }
                catch (WebException ex)
                {
                    MessageBox.Show("Exception: " + ex.Message + " " + ex.Response + " status:" + ex.Status + " target:" + ex.TargetSite + " source:" + ex.Source);
                }


            }
            catch (WebException error)
            {
                rtOutput.Text = "Error encountered: " + error.ToString();
            }

            Cursor.Current = Cursors.Default;
        }

THE DATA WE ARE Submitting:

<?xml version="1.0" encoding="UTF-8"?><atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><atom:content type="application/xml"><m:properties><d:Mandt>022</d:Mandt><d:Pernr>10000000</d:Pernr></m:properties></atom:content></atom:entry>

The HTTP Web exception occurs on the following:

try

                {

                    httpWebResponse = (HttpWebResponse)httpRequest.GetResponse();

                }

                catch (WebException ex)

                {

                    MessageBox.Show("Exception: " + ex.Message + " " + ex.Response + " status:" + ex.Status + " target:" + ex.TargetSite + " source:" + ex.Source);

                }

If anyone has succesfully integrated a PUT/POST to SAP Netweaver using .net framework c#, please provide some input on the above mentioned issues.

Thank you and I look forward to your responses.

Kind regards,

--Edwin Ramos

Accepted Solutions (0)

Answers (3)

Answers (3)

di_deng
Explorer
0 Kudos

Hi you may try storing your session cookies.

Former Member
0 Kudos

Hi you may try storing your session cookies.

Would you post your code to do this ? I am having the exact same issue (see https://scn.sap.com/thread/3956649)

I followed a couple of other  posts that describe saving cookies to fix this issue but they did different (and incompatible) things and neither worked for me.

Martin



Former Member
0 Kudos

Hi Gaurav,

Good suggestion,

We are reaching SAP NWG because if a wrong UID and PWD is sent

we get a http 401 unauthorised.

The test code is executed within internal machine and not going through DMZ.

I will check the internal web dispatcher if this is filter a POST request, but not sure if this is applicable.

Any other suggestions are welcomed.

Thanks once again.

Kind regards,

--Edwin

Former Member
0 Kudos

Hi Edwin,

Check the following Tcodes in abap stack for NetWeaver Gateway/IWFND/ERROR_LOG


and

Activate the traces and run the service again

/IWFND/TRACES


Regards

Gaurav Ahluwalia


Former Member
0 Kudos

Hi Guarav,

We have turned on the traces. Great! thank you for this pointer.

The HTTP 403 as mentioned  based on the log:

CSRF validation failed for the user, which is confusing because we are definitely setting the header

prior to making the http web request:

See below:-

//set the Token

               httpRequest.Headers.Add("X-CSRF-Token", gcsrfToken);


                //set the cookie
               httpRequest.Headers.Add("Set-Cookie", gsetCookie);


                //check the header is applied before sending
  gcsrfToken = httpRequest.Headers.Get("X-CSRF-Token");

Is there anyway know what the payload or http header received by the server.

Fiddler would be good to run but unable to install this on machine due to security.

regards,

Edwin

Former Member
0 Kudos

HI Edwin,

Please use Postman Client in Google Chrome.

Regards

Gaurav Ahluwalia

Former Member
0 Kudos

Hi Guarav,

Our Basis team did the system tracing and have checked the payload received by SAP NG;

1. confirm that the same X-CSRF-Token values are the same from the GET response and the POST request.

2. we added a HTTP header parameter
“X-Requested-With=XMLHttpRequest “

and then disable check_csrf_token in SICF

and still get a HTTP 403 response- the trace comes back with CSRF validation failed.

Such a painful experience and I am sure someone has come across this issue before and managed to fully resolve.

Do you have any more suggestions.

regards,

Edwin

Former Member
0 Kudos

Hi Edwin,

Check whether the CSRF Token validation is suppressed to the service in SICF

Cross-Site Request Forgery Protection - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library

Go through this link and check whether the token validation mechanism in sap has bee successfully activated

Regards

Gaurav Ahluwalia

Former Member
0 Kudos

Hi Edwin,

Follow the following

1) Retrieve a CSRF token with a non-modifying request

field X-CSRF-Token. This happens in a non-modifying request (such as GET) if the header field X-CSRF-Tokenwith the value Fetch


2)

Modify the request without CSRF token

For all modifying requests the application must include this token in an HTTP request header field with the same name ( X-CSRF-Token). The framework checks for all modifying requests the validity of the CSRF token in the request. The validation is done by the ICF runtime that checks against the token from the "anti-XSRF cookie". If the validation fails an HTTP status code 403 (Forbidden) is sent back.

for this login/ticket_only_by_https is set to 0 By setting the value of this profile parameter to 0, you can enable the use of cookies for HTTP.

SAP NetWeaver Gateway offers two CSRF protection mechanisms

  • CSRF token check
  • CSRF header parameter check- X-Requested-With=XMLHttpRequest for modifying operations as protection mechanism. This is the default for the Compatibility Mode for SP02.

3) Changing the Default CSRF Protection Mechanism

  • Parameter Name: ~CHECK_CSRF_TOKEN
  • Parameter Value: 0/1 (disable/enable)


4) Compatiblity Mode for SP02 - HTTP Handler in SICF (node sdata)

( Default : X-Requested-With, to enable XSRF check use, ~CHECK_CSRF_TOKEN=1)

The request handler is /IWFND/CL_SDATA_ODATA_APP.

Standard Mode - HTTP Handler in SICF (node odata)

( Default: XSRF check, to disable and switch to X-Requested-With, use~CHECK_CSRF_TOKEN=0) The request handler is /IWFND/CL_SODATA_HTTP_HANDLER.

Regards

Gaurav Ahluwalia


Former Member
0 Kudos

Hi Edwin

Check X-CSRF Token Validation which is Cross Site Forgery Protection

Best to post a document with X-CSRF Token is to query the ODATA service document

and in the header of Request and  send X-CSRF-Token : fetch  in the header and use the token to post

see this URL

HTTP header X-CSRF-Token value as fetch


CSRF Protection - Connectivity - SAP Library

Using the CSRF Token - SAP Mobile Documents - SAP Library

Regards

Gaurav Ahluwalia

Former Member
0 Kudos

Hi Gaurav,

Good response but we know that have a value coming back from the GET request for X-CSRF Token and 100% certain we set the same value received to the http header using http header.add.

I am also explicity printing out the values to make sure it matches the same as what the get function has received.

best regards,

-Edwin

Former Member
0 Kudos

HI Edwin,

Check the logs of Reverse proxy or the Relay Server in DMZ if you accessing it from internet

Whether it is an error in dispatcher.

Or

check the logs of Internal web dispatcher

Regards

Gaurav Ahluwalia