1

My goal is to send user comments with a POST request from a server-side Lambda function to my WordPress API. I'm using Gatsby and Netlify.

When someone leaves a comment in the comment form of my Gatsby front-end, Netlify receives a form submission event and a Netlify Lambda function gets called. It is in this function that I will prepare and send the comment to my WordPress site through the WP-REST API.

The problem is that my function seems to fail silently. This may be partly due to how Netlify makes available its Functions logs. My hunch was that some form of Authentication was needed to POST a comment to WP REST API so I went ahead and installed the JWT Authentication Plugin (mainly because I believe it is more secure that Basic Auth, though I'm not sure).

I went through the docs for the JWT plugin and made the necessary changes to my .htaccess and my wp-config.php file including enabling CORS support and defining a new secret key:

define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key');

In my Lambda function I make a post request the end JWT endpoint:

fetch('https://example.com/wp-json/jwt-auth/v1/token', {
     // credentials: 'include',
     headers: new Headers({
        'Authenticate': 'Basic {what do I put here?}' // Do I need "Basic"?
     })
  })
  .then(response => {
     console.log("Did we get a response? ", response)
     return response.json()
  })
  .then(myJson => {
     console.log(JSON.stringify(myJson))
  })
  .catch(error => {
     console.log("error: ", error);
     throw new Error('Something bad happened.', error)
  })

My confusion comes in how to properly set up an Authentication call, if I need to authenticate at all, and whether or not I should be sending my WordPressusername:password or the JSON Web Token that I defined in my wp-config.php.

And what should the format of the username/password be? Should it URL-encoded, i.e: username=admin&password=Str0ngPass or just `username:password'.

This question seems to offer a working approach but I am not using Postman and can't even get a token from my Fetch call. A couple more answers that I found are more theoretical and don't offer much in terms of code examples:

I also discovered JWT Web Tokens for Node. Maybe I should implement it that way?

I've found the documentation surrounding using fetch to authenticate to be a little patchy. Any help would be greatly appreciated and I'm happy to supply any more code/info that you need.

2
'Authenticate': 'Basic {what do I put here?}' // Do I need "Basic"?

No, it's not Basic. It's Bearer. And the header is Authorization.

So first, obtain a token from /wp-json/jwt-auth/v1/token:

fetch( 'http://example.com/wp-json/jwt-auth/v1/token', {
    method: 'POST',
    body: JSON.stringify( {
        // Username of a user on the WordPress website in which the REST API request
        // is being made to.
        username: 'user',
        // And the above user's password.
        password: 'pass'
    } ),
    headers: {
        'Content-Type': 'application/json'
    }
} )
.then( res => res.json() )
.then( res => console.log( res.token ) );

At this point: .then( res => console.log( res.token ) ), you can cache the token, for example in the browser cookies (document.cookie). I mean, if there were no errors (returned by the REST API endpoint), then the token is stored in res.token.

After you obtained a valid token, you can then use the token when making a request to a REST API endpoint such as "Create a Comment" — set the Authorization header and set its value to: Bearer <token>, where in the above example, <token> is the value of the res.token.

fetch( 'http://example.com/wp-json/wp/v2/comments', {
    method: 'POST',
    body: JSON.stringify( {
        author_email: 'test@example.com',
        author_name: 'Test via REST API',
        content: 'Test comment',
        post: 123
    } ),
    headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer <token>'
    }
} )
.then( res => res.json() )
.then( res => console.log( res ) );

Make sure the Authorization header is enabled

Because that header is required by the plugin.

And in my case, the Authorization header (which in PHP can be accessed via $_SERVER['HTTP_AUTHORIZATION']) was missing/disabled, so I had to add this to the Apache's configuration file (httpd.conf): (requires restarting the Apache server)

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

I did try to add this to the (root) .htaccess file, but it didn't work for me:

RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]

I hope that helps you and/or someone else having problems with the Authorization header. :)

Resources

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.