DEV Community

Andrew Elans
Andrew Elans

Posted on

Power Pages SPA - emulate ajaxSafePost with fetch

If you have Single Page Application setup with Power Pages, you may lack the global object shell which has a function called ajaxSafePost that uses antiforgery token to make HTTP requests in Power Apps.

One of the latest features added to Power Pages is ability to trigger a Power Automate flow from a Power Pages web site and get response back from the flow.

This feature be used for different purposes which I may experiment with later, but let's look in this post on how to set it up.

We will use Power Automate trigger When Power Pages calls a flow and action Return value(s) to Power Pages. Between these we may have whatever logic we want.

The trigger When Power Pages calles a flow (learn.microsoft.com/en-us/power-pages/configure/cloud-flow-integration) can only be invoked if a Cross-Site Request Forgery (CSRF) token is present in the HTTP header.

Default Power Pages setup with a standard template, for example Default studio template provides a global object called shell (available in dev tools' console) that has a function ajaxSafePost which when called includes CSRF token in the request. But when we have an SPA setup, we don't use standard templated, hence don't have any of the provided functions.

But we still have access to the CSRF token provided on page <your-site-url>/_layout/tokenhtml. Looking at the source of this page we will find the only HTML element available there - input, value is exactly our CSRF:

<input name="__RequestVerificationToken" type="hidden" value="oB5JWfV1FbaiC7Yb6iIIol-m4q4aVjjr3Es-rNj3kw-8XBUxeYLceO7ImbsnejH98CGSz59RujtIi2g41xrxJYb42lYXayl7ZFZ_0r_B-KzXw50VSZOfdBFo31Bj3rgKJe6Tc9uUsVyTDEoYPL8LQw2">
Enter fullscreen mode Exit fullscreen mode

ajaxSafePost will look like this:

shell.ajaxSafePost({
    type: "POST",
    url: "/_api/cloudflow/v1.0/trigger/88b95a74-8570-f011-b4cc-000d3ad91bc3",
    data: {"eventData":JSON.stringify({})}
})
.done(console.log)
Enter fullscreen mode Exit fullscreen mode

To do the same with the Fetch API when the shell object is not provided:

fetch('/_layout/tokenhtml').then(res => res.text()).then(
    (text) => {
        const doc = new DOMParser().parseFromString(text, "text/xml");
        const input = doc.querySelector("input");
        const token = input.getAttribute("value");
        fetch(
            '/_api/cloudflow/v1.0/trigger/88b95a74-8570-f011-b4cc-000d3ad91bc3'
            , {
                  method: 'POST', 
                  body:  new URLSearchParams({ eventData: JSON.stringify({})}), 
                  headers: {
                      "__RequestVerificationToken": token, 
                      "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                      "x-requested-with": "XMLHttpRequest"
                  }
            }
        ).then(res => res.text()).then(console.log)
    }
)
Enter fullscreen mode Exit fullscreen mode

Being authenticated to the portal and opening the dev tools and calling this code in the console, I get this response back:

{"response":"hi from flow!"} -> this is a text response I added on action Return value(s) to Power Pages.

Note: the flow is setup in make.powerpages.microsoft.com -> Set up -> Cloud flows so that it can be called only by the authenticated in portal users. If I call this code being not authenticated (for example when opening <your-site-url>/_layout/tokenhtml in the inkognito mode, this page can be opened by anyone as explained in this post dev.to/andrewelans/power-pages-spa-login-redirect-2g2n), I get this error back: {"ErrorCode":"00000003","Message":"MissingPermissions"}

Top comments (0)