1
static void createListItem(string sharepointUrl, string Cookie,string formDigest, string newItemName, string listId)
    {
        //Execute a REST request to add an item to the list.
        string itemPostBody = "{'__metadata':{'type':'" + "SP.Data.T1ListItem" + "'}, 'Title':'" + "T1" + "'}}";
        Byte[] itemPostData = System.Text.Encoding.ASCII.GetBytes(itemPostBody);

        HttpWebRequest itemRequest =
            (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "/_api/Web/lists(guid'" + listId + "')/Items");
        itemRequest.Method = "POST";
        itemRequest.ContentLength = itemPostBody.Length;
        itemRequest.ContentType = "application/json;odata=verbose";
        itemRequest.Accept = "application/json;odata=verbose";
        itemRequest.Headers.Add(@"Cookie:" + Cookie);
        itemRequest.Headers.Add(@"X-RequestDigest", formDigest);
        Stream itemRequestStream = itemRequest.GetRequestStream();

        itemRequestStream.Write(itemPostData, 0, itemPostData.Length);
        itemRequestStream.Close();

        try
        {
            HttpWebResponse itemResponse = (HttpWebResponse)itemRequest.GetResponse();
        }
        catch(Exception e)
        {
            Console.WriteLine(e.InnerException);
            Console.WriteLine(e.Message);
            Console.WriteLine(e.StackTrace);
            Console.ReadLine();

        }

    }

I am trying to access my O365 site from a C# console application using REST apis (I am not allowed to use CSOM as the solution has to be migrated to JAVA applications too). I am using Cookie Authentication and FormDigest for this purpose. I have had limited success as I am able to read lists using GET request. Using same Cookies and Form Digest But unfortunately I have to Create folders, List Items etc. Every time I try to create a List Item or Folder I am getting a Forbidden:403 error. I am the Site Collection Administrator, and I am using a Full Control Account for the Authentication.

In the above example, I am trying to create an item (Title Only) in a list named "T1". I am getting 403 when I attempt it.

Please Help!

Edit: I used this method by Paul Rayn. SHAREPOINT ONLINE REMOTE AUTHENTICATION

  • i am guessing here! most likely, the effective permissions are not the user running the app but the app itself. get the token for the user and if the user has sufficient permissions should work! – Vamsi K K Mar 8 '17 at 19:58
  • It is not an app. It is a console application and I am using the admins username and password to generate rFta and FedAuth cookies and then using the cookies to get the Form Digest to use in the HTTP POST request. If it is not the Admin User's permissions then whose permissions could it be using? Awaiting your feedback. Thanks. – Sector555 Mar 8 '17 at 21:10
  • Doesn't help your current situation, but you should look into JSON Light. Gets rid of the need to include the metadata portion of the POST. – wjervis Mar 10 '17 at 12:00
  • @wjervis Sure I will give that a try the next time. Thanks :) – Sector555 Mar 10 '17 at 12:11
0

Remotely access SharePoint Online documents

The above article by Pallav, helped me to correct the errors. The error was occurring as I had not passed the RpsContextCookie with requests. But the GET operation still worked with just rtFa and FedAuth Cookies and Form Digest values. Don't really know why that happened.

Posting full code. Hope it helps.

using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

namespace SharePointCookie
{
class Program
{

    static void Main(string[] args)
    {
        var username = "[Username for SharePoint Online]";
        var password = "[Password]";
        var endPoint = "[SharePoint Online site url]";
        var stsEndpoint = "https://login.microsoftonline.com/extSTS.srf";
        var signInUrl = "https://[SharePointOnlineDomain].sharepoint.com/_forms/default.aspx?wa=wsignin1.0";
        var browserHost = "[SharePoint Online domain]"; //e.g. mycompany.sharepoint.com 
        var browserUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36";

        var cookies = new CookieContainer();
        var SMAL = "[SMAL XML]";
        var payLoadSts = SMAL.Replace("{USERNAME}", username).Replace("{PASSWORD}", password).Replace("{ENDPOINTREFERENCE}", endPoint);

        // webrequest 0 
        // webrequest 0: get the RpsContextCookie 
        // webrequest 0 
        string requiredAuthUrl = string.Format("{0}/_layouts/15/Authenticate.aspx?Source={1}", endPoint, HttpUtility.UrlDecode(endPoint));
        HttpWebRequest request0 = (HttpWebRequest)WebRequest.Create(requiredAuthUrl);
        request0.Accept = "*/*";
        request0.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US");
        request0.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
        request0.UserAgent = browserUserAgent;
        request0.AllowAutoRedirect = false;
        request0.CookieContainer = cookies;

        var response0 = (HttpWebResponse)request0.GetResponse();

        // webrequest 1
        // webrequest 1: login
        // webrequest 1
        var request1 = (HttpWebRequest)WebRequest.Create(stsEndpoint);
        request1.CookieContainer = cookies;
        var data = Encoding.ASCII.GetBytes(payLoadSts);

        request1.Method = "POST";
        request1.ContentType = "application/xml";
        request1.ContentLength = data.Length;

        using (var stream1 = request1.GetRequestStream())
        {
            stream1.Write(data, 0, data.Length);
        }

        // Response 1
        var response1 = (HttpWebResponse)request1.GetResponse();
        var responseString = new StreamReader(response1.GetResponseStream()).ReadToEnd();

        // Get BinarySecurityToken
        var xData = XDocument.Parse(responseString);
        var namespaceManager = new XmlNamespaceManager(new NameTable());
        namespaceManager.AddNamespace("S", "http://www.w3.org/2003/05/soap-envelope");
        namespaceManager.AddNamespace("wst", "http://schemas.xmlsoap.org/ws/2005/02/trust");
        namespaceManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        var BinarySecurityToken = xData.XPathSelectElement("/S:Envelope/S:Body/wst:RequestSecurityTokenResponse/wst:RequestedSecurityToken/wsse:BinarySecurityToken", namespaceManager);

        // webrequest 2
        // webrequest 2 //_forms/default.aspx?wa=wsignin1.0
        // webrequest 2
        var request2 = (HttpWebRequest)WebRequest.Create(signInUrl);

        var data2 = Encoding.ASCII.GetBytes(BinarySecurityToken.Value);
        request2.Method = "POST";
        request2.Accept = "*/*";
        request2.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US");
        request2.ContentType = "application/x-www-form-urlencoded";
        request2.UserAgent = browserUserAgent;
        request2.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
        request2.Host = browserHost;
        request2.ContentLength = data2.Length;
        request2.CookieContainer = cookies;

        using (var stream2 = request2.GetRequestStream())
        {
            stream2.Write(data2, 0, data2.Length);
        }

        // Response 2
        var response2 = (HttpWebResponse)request2.GetResponse();
        var responseString2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();


        // webrequest 3
        // webrequest 3: get X-RequestDigest 
        // webrequest 3
        string restUrl3 = string.Format("{0}/_api/contextinfo", endPoint);
        var request3 = (HttpWebRequest)WebRequest.Create(restUrl3);
        request3.CookieContainer = cookies;
        request3.Method = "POST";
        request3.ContentLength = 0;

        // Response 3
        string formDigest = string.Empty;
        using (var response3 = (HttpWebResponse)request3.GetResponse())
        {
            using (var reader = new StreamReader(response3.GetResponseStream()))
            {
                var result = reader.ReadToEnd();

                // parse the ContextInfo response
                var resultXml = XDocument.Parse(result);

                // get the form digest value
                var x = from y in resultXml.Descendants()
                        where y.Name == XName.Get("FormDigestValue", "http://schemas.microsoft.com/ado/2007/08/dataservices")
                        select y;
                formDigest = x.First().Value;
            }
        }

        //Rest Call 1 
        string restUrl = string.Format("{0}/_api/web/GetFolderByServerRelativeUrl('/Shared%20Documents')/files", endPoint);
        var req = (HttpWebRequest)WebRequest.Create(restUrl);
        req.CookieContainer = cookies;
        req.Method = "GET";
        req.Accept = "application/json; odata=verbose";
        req.ContentType = "application/json;odata=verbose";
        req.Headers.Add("X-RequestDigest", formDigest);
        var resp = (HttpWebResponse)req.GetResponse();
        var respStr = new StreamReader(resp.GetResponseStream()).ReadToEnd(); 

        //Rest Call 2
        restUrl = string.Format("{0}/_api/Web/GetFileByServerRelativeUrl('/Shared Documents/doc.docx')/$value", endPoint);
        req = (HttpWebRequest)WebRequest.Create(restUrl);
        req.CookieContainer = cookies;
        req.Method = "GET";
        req.Accept = "application/json; odata=verbose";
        req.ContentType = "application/json;odata=verbose";
        req.Headers.Add("X-RequestDigest", formDigest);
        resp = (HttpWebResponse)req.GetResponse();
        respStr = new StreamReader(resp.GetResponseStream()).ReadToEnd(); 


    }


}

}

  • In my experience, the cookies aren't needed for GET's, but for POST's and PUT's. – jedmeyer Aug 6 '18 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.