0

I am attempting to automate the check out of a file on my company's SharePoint Online server. I am doing this with Python (2.7.11) and the requests library. Using MSDN Docs I've come accross this example POST:

executor.executeAsync({
  url: "<app web url>/_api/SP.AppContextSite(@target)/web
    /getfilebyserverrelativeurl('/Shared Documents/filename.docx')
    /checkout
    ?@target='<host web url>'",
  method: "POST",
  success: successHandler,
  error: errorHandler
});

Filling in the placeholders, when I POST the URL I get a 403 response. This does not make sense to me because:

  1. I am correctly authenticated to the server using my SharePoint Online credentials (elsewise I would've received a 401). The authentication is provided in the form of cookies in the header of the request.
  2. I've confirmed that my SharePoint Online account has the permissions to perform this action by doing it manually in browser

Why does SharePoint treat my manual user actions and the POST differently by providing the 403 error? Is there some other data (aside from the authentication) I need to provide with the POST for SharePoint to know its me?

EDIT

The following message is sent back with the 403 status:

The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.

This is odd because I know the authentication process goes smoothly because I get cookies back. The browser isn't saying I have bad credentials by giving me a 401 error. What could cause this?

EDIT 2

After doing some more reading, I initially thought my solution would be to set AllowUnsafeUpdates to true, however, based on this question, I should not need to do this if I provide the form digest. I confirmed that the digest is included in the POST, shouldn't this remove the need to fiddle with AllowUnsafeUpdates?

My POST now looks something like this (with placeholders filled in):

URL:

"https://mycompany.sharepoint.com/sites/stuff/_api/SP.AppContextSite(@target)/web/getfilebyserverrelativeurl('<filePath>')/checkout"

Headers:

content-type: application/json;odata=verbose

Cookie: FedAuth=blahblahblah; rtFa=blahblahblah

accept: application/json;odata=verbose

__REQUESTDIGEST: 0xF9CA....

Data:

target: "https://mycompany.sharepoint.com/"

closed as off-topic by Eric Alexander Apr 12 '16 at 14:38

  • This question does not appear to be about SharePoint within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • I'm voting to close this question as off-topic because I originally posted this question because I was unsure of the SharePoint specific issues my code faced. However, I now understand what I need to do, but not how to do it. As such, this question is more fit for StackOverflow as it deals with the code implementation rather than SharePoint specific questions (per the user) – Eric Alexander Apr 12 '16 at 14:38
1

You need to pass the headers and the request digest to check out the file like below:

executor.executeAsync({
  url: "<app web url>/_api/SP.AppContextSite(@target)/web
    /getfilebyserverrelativeurl('/Shared Documents/filename.docx')
    /checkout
    ?@target='<host web url>'",
  method: "POST",  
  headers: {
        "Accept": "application/json; odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val()
        },
  success: successHandler,
  error: errorHandler
});

Another method to checkout is as below:

function CheckOutFile()
{
var digest = ""; 
$.ajax(
{
                url: _spPageContextInfo.webAbsoluteUrl + "/_api/contextinfo",
                method: "POST",
                headers: {
                                "ACCEPT": "application/json;odata=verbose",
                                "content-type": "application/json;odata=verbose"
                },
                success: function (data) {
                digest = data.d.GetContextWebInformation.FormDigestValue;
                },
                error: function (data) {                               
                }
}).done(function() {
                                $.ajax(
                                {                                             
                                                url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/GetFileByServerRelativeUrl('/Shared Documents/filename.docx')/CheckOut()",
                                                method: "POST",                                            
                                                headers: {
                                                                "ACCEPT": "application/json;odata=verbose",
                                                                "X-RequestDigest": digest
                                                },    
                                                success: function (data) {                                            
                                                                alert("Checked out");                                   
                                                },
                                                error: function (data) {
                                                                alert("Error occured." + data.responseText);
                                                }
                                });                          
                });                                 
}
  • $("#__REQUESTDIGEST").val() looks like a function call, so doesn't this just return the diget value? If so and the header is just X-RequestDigest: 0xA2D9.... then this is already what I'm doing – wnnmaw Apr 1 '16 at 12:31

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