0

I have an HTML form that I am trying to send (POST). And I keep getting the following 403 error: The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again.

I have read several other posts and tried the accepted answer (make another request before my Post to _api/contextInfo and I continue to get the same error

value: "The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again."

Here is my updated script per Dylan Cristy's answer:

fetch("/_api/contextinfo", {
    method: "POST",
    headers: {
        "Accept": "application/json;odata=verbose",
    }
}).then(contextResponse => {

    // get the form digest value that you _would_ have gotten from $('#__REQUESTDIGEST').val()

    var requestDigest = contextResponse.GetContextWebInformation.FormDigestValue;

    // now use it in your next request

    fetch("/_api/web/lists/getbytitle(LeaveRequestPost)/items", {
        method: "POST",
        credentials: 'same-origin',
        body: JSON.stringify(item),
        headers: {
            "Accept": "application/json; odata=nometadata", // or odata=verbose|minimalmetadata  (minimalmetadata is default if odata not specified)
            "Content-Type": "application/json; odata=nometadata", // or odata=verbose|minimalmetadata  (minimalmetadata is default if odata not specified)
            "X-RequestDigest": requestDigest
        }
    });
});

UPDATE

Now I am getting the following issues:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'FormDigestValue').

The response in the Network Tab shows as contextInfo and contains the value shown below, but when I console.log contextResponse, it does not provide .GetContextWebInformation.

{
  "d": {
    "GetContextWebInformation": {
      "__metadata": {
        "type": "SP.ContextWebInformation"
      },
      "FormDigestTimeoutSeconds": 1800,
      "FormDigestValue": "FormDigestValue_Value",
      "LibraryVersion": "LibraryVersionValue",
      "SiteFullUrl": "SiteFullUrlValue",
      "SupportedSchemaVersions": {
        "__metadata": {
          "type": "Collection(Edm.String)"
        },
        "results": [
          "14.0.0.0",
          "15.0.0.0"
        ]
      },
      "WebFullUrl": "WebFullUrlValue"
    }
  }
}
5
  • 1
    Is this code running on a SharePoint page/site? Also, are you using/loading jQuery? Commented Jun 24, 2022 at 17:55
  • Hey Dylan, it is running on a SharePoint site, it is a custom html page which I converted to .aspx, the operations I am running don't require any of the default .aspx sharepoint scripts so I don't think that would be an issue.
    – BeerusDev
    Commented Jun 24, 2022 at 17:58
  • 1
    Are you loading jQuery on your custom page? Commented Jun 24, 2022 at 18:15
  • Yes, I am loading jQuery
    – BeerusDev
    Commented Jun 24, 2022 at 18:16
  • 1
    You should post your new error about the primitive value as a separate question. Commented Jun 27, 2022 at 15:57

1 Answer 1

3

So, when you're making a request to /_api/contextinfo to get around not being able to get the request digest from

$('#__REQUESTDIGEST').val()

you have to wait for the response, and then use the returned form digest token in your next request in the same "X-RequestDigest" header. It's not enough to just hit the endpoint with a POST.

fetch("/_api/contextinfo", {
    method: "POST",
    headers: {
        "Accept": "application/json;odata=verbose",
    }
}).then(contextResponse => {

    // get the form digest value that you _would_ have gotten from $('#__REQUESTDIGEST').val()

    var requestDigest = contextResponse.d.GetContextWebInformation.FormDigestValue;

    // now use it in your next request

    fetch("/_api/web/lists/getbytitle(LeaveRequestPost)/items", {
        method: "POST",
        credentials: 'same-origin',
        body: JSON.stringify(item),
        headers: {
            "Accept": "application/json; odata=nometadata", // or odata=verbose|minimalmetadata  (minimalmetadata is default if odata not specified)
            "Content-Type": "application/json; odata=nometadata", // or odata=verbose|minimalmetadata  (minimalmetadata is default if odata not specified)
            "X-RequestDigest": requestDigest
        }
    });
});

Note that in my example, in the first request I changed to odata=verbose because I was just verifying on a SP 2013 site and you have to use odata=verbose on 2013, and if you change to odata=nometadata it might change the structure of the response slightly. I'm guessing there won't be a d property so it might be something more like

var requestDigest = contextResponse.GetContextWebInformation.FormDigestValue;

In any case, the idea is the same - you hit the /api/contextinfo enpoint to get the form digest value, but you have to then use that value in your next request.


I forgot you are using fetch, and when you use fetch the response object doesn't automatically resolve into the JSON data you requested, you have to call json() on the response to get the JSON data (which is another async operation). So you'll need to do something like this:

fetch("/_api/contextInfo", {
    method: "POST",
    headers: {
        "Accept": "application/json;odata=verbose",
    }
}).then(contextResponse => {

    // when using fetch you have to explicitly
    // get the response json which is another async operation

    if (contextResponse.ok) {

        contextResponse.json().then(responseJson => {

            // get the form digest value that you _would_ have gotten from $('#__REQUESTDIGEST').val()

            var requestDigest = responseJson.d.GetContextWebInformation.FormDigestValue;

            // now use it in your next request

            fetch("/_api/web/lists/getbytitle(LeaveRequestPost)/items", {
                method: "POST",
                credentials: 'same-origin',
                body: JSON.stringify(item),
                headers: {
                    "Accept": "application/json; odata=nometadata", // or odata=verbose|minimalmetadata  (minimalmetadata is default if odata not specified)
                    "Content-Type": "application/json; odata=nometadata", // or odata=verbose|minimalmetadata  (minimalmetadata is default if odata not specified)
                    "X-RequestDigest": requestDigest
                }
            });
        })
    }
});
6
  • When I use this method, I no longer the previous error when but I do get this error Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'GetContextWebInformation'). When looking at the response in the network tab, I do get the value for the formdigestvalue
    – BeerusDev
    Commented Jun 27, 2022 at 13:04
  • In regards to the above comment, that was with the d property in requestDigest. When I remove the d property, I get the following Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'FormDigestValue'). Please see the update to my post with an example of the response
    – BeerusDev
    Commented Jun 27, 2022 at 13:45
  • it shows in the Network tab as contextInfo, when I console.log contextResponse there is no GetContextWebInformation
    – BeerusDev
    Commented Jun 27, 2022 at 15:02
  • 1
    @BeerusDev updated my answer Commented Jun 27, 2022 at 15:13
  • That fixed that issue, but now I am receiving another error. Please check the update to my OP if you are available
    – BeerusDev
    Commented Jun 27, 2022 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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