Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't load forms in a headless single page application in different domain / Improve error handling among other things #9

Open
k1sul1 opened this issue May 25, 2021 · 1 comment
Labels
enhancement New feature or request workaround inside

Comments

@k1sul1
Copy link
Member

k1sul1 commented May 25, 2021

Describe the bug
If this component is used without a window.wplfData in place, it will fail with a cryptic "Unexpected token at 0".

If the request to the form is 403'd for some reason (nonce!!) it will display the loading state forever, in my case:

image

To Reproduce
Steps to reproduce the behavior:

  1. Install the component from npm
  2. Import it and use it in code without supplying wplfData
  3. See error

In other words, headless single page applications are in quite a spot at the moment.

@k1sul1 k1sul1 added bug Something isn't working enhancement New feature or request workaround inside and removed bug Something isn't working labels May 25, 2021
@k1sul1 k1sul1 changed the title Improve error handling among other things Can't load forms in a headless single page application in different domain / Improve error handling among other things May 25, 2021
@k1sul1
Copy link
Member Author

k1sul1 commented May 25, 2021

So... When used normally, WPLF adds an object to window.wplfData. The object looks something like this.

window.wplfData = {
  "backendUrl": `${config.apiHost}/wp-json/wplf/v2`,
  "fetchCredentials": "same-origin",
  "requestHeaders": {
    "X-WP-Nonce": "6511690583"
  },
  "assetsDir": `${config.apiHost}/wp-content/plugins/libreform/assets`,
  "settings": {
    "autoinit": true,
    "parseLibreformShortcodeInRestApi": true,
    "hasUnfilteredHtml": true,
    "debugLevel": "errors"
  },
  "i18n": {
    "problems": "Problems: ",
    "duplicateFieldName": "Duplicate field name: ",
    "illegalName": "You can't use {name} as a name, as it conflicts with a core field name.",
    "fieldAlreadyExistsInDb": "Field already exists in the database with the type {type}, use a different name or remove the field first.",
    "groupedNamesNotSupportedYet": "Field names like these are not supported yet. Try using camelCasing or under_scores for grouped names instead.",
    "noSubmissionsYet": "No submissions yet.",
    "loading": "Loading...",
    "delete": "Delete",
    "edit": "Edit",
    "close": "Close",
    "export": "Export",
    "attachment": "Attachment",
    "emptyField": "(empty)",
    "formSubmission": "Form submission",
    "noUnfilteredHtml": "You don't have enough permissions to save HTML, which means you can't edit forms. You can view the submissions and examine the options, but you can't change anything in the form.",
    "deleteSubmissionsPrompt": "Delete selected submissions?",
    "formSubmissionRequestFailed": "Request to submit form failed",
    "unableToAttachWPLF": "Unable to attach WPLF to element"
  }
}

Obviously I have already replaced the actual domain with the variable in the example, but this is more or less what you get. The JS in the plugin requires this object to work, and the JS in this component requires the JS in the plugin to work, so you can't skip this.

So here's where it gets interesting. Because we add the nonce to the base request headers, all form submissions by users who are logged in will be authenticated, when we're dealing with traditional WordPress with cookies and shit. If you use this component in a WordPress site, it will work like you'd expect.

However, when you use the component in a single page application, you lose the standard authentication of WordPress which works with cookies. This means that there will be no WP cookies sent with the submission, and getting the nonce from the API is a terrible idea. While you can do it, don't. I've already done it so you wouldn't have to.

So... Let's say you copypasted the wplfData object and you're getting a 403 when you try to load a form. Behind that 403 is more than likely to be a "nonce is invalid" error message, at which point I wouldn't blame you if you wanted to facedesk.

Worry not. I give you 3 options.

  1. Get rid of the nonce. Seriously. It is not required to submit forms, but if you supply a wrong nonce, things will break. If you don't need authentication, do this. How? Replace the old requestHeaders with requestHeaders: {}. You just need to overwrite the old object so the nonce isn't sent.
  2. Use a proper authentication method such as OAuth. Speaking from experience, this is hard. Very.
  3. Use a proxy server (think Express) to manage SESSIONS and API REQUESTS for you. Instead of making direct calls to WP API, make them to the proxy, which will proxy them to the API. This is simpler than it sounds. Combine this idea with express-session, https://github.com/WP-API/Basic-Auth and you're good to go. I've done this before, here's a QUICK example; https://gist.github.com/k1sul1/0b6a08ffbf01ac77df4f8a72d6fb5bcd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request workaround inside
Projects
None yet
Development

No branches or pull requests

1 participant