reactjsjira-rest-apicors-anywhere

React + Atlassian Jira Cloud Api + Cors Anywhere: Adding a worklog via POST returns 403


Been stuck on this for a few days now. I'm making an app in React that uses Atlassian's Jira Cloud Rest API and I want to log work on a Jira issue from my app. However every time I try I get a 403. The same request in Postman works, it creates the worklog, which is weird. I set up a certificate and use cors-anywhere to be able to use HTTPS in my React app, but otherwise the query is the same.

I've read a bunch of entries on Atlassian's forums about people being unsure about what to do when they need to POST to an Atlassian API. Is this something bizarre that can't be fixed, or am I missing a relevant header?

Here is the fetch call I make in my React app's ComponentDidMount(). https://localhost:8080 is the proxy I use for CORS-anywhere/Yarn.

fetch("https://localhost:8080/my-domain.atlassian.net/rest/api/2/issue/ISSUE-1/worklog,{
            headers: {
              "Access-Control-Allow-Origin": "https://localhost:3000/",
              "X-Atlassian-Token": "no-check",
              "Content-Type": "application/json;charset=UTF-8",
              "Authorization": "Basic base64token",

            },
            method: "POST",
            responseType: 'json',
            body: {
                 "timeSpent":"2h 48m",
                 "author":{
                      "accountId":"123456789",      
                      "active":true,
                      "avatarUrls":{
                             "16x16":"https://avatar-cdn.atlassian.com/...",
                             "24x24":"https://avatar-cdn.atlassian.com/...",
                             "32x32":"https://avatar-cdn.atlassian.com/...",
                             "48x48":"https://avatar-cdn.atlassian.com/..."
                      },
                      "displayName":"User Name", 
                      "emailAddress":"user.name@gmail.com",
                      "key":"user.name",
                      "name":"user.name",
                      "self":"https://my-domain.atlassian.net/rest/api/2/user?username=user.name",
                      "timeZone":"Europe/Stockholm"
                  },
                  "comment":"bla bla bla",
                  "started":"2018-07-19T21:32:18.843+0200"
             }
        })
        .then((res) => res.json())
        .then(function(resJson){ 
            console.log(resJson
        })

And this is my server.js that Yarn runs.

const path = require('path')
const fs = require('fs')
const express = require('express')
const https = require('https')

const app = express();
const host = process.env.HOST || '0.0.0.0';
const port = process.env.PORT || 8080;

const cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
    httpsOptions: {
        key: fs.readFileSync(path.resolve('server.key')),
        cert: fs.readFileSync(path.resolve('server.crt'))
    },
    originWhitelist: ['https://localhost:3000', 'https://localhost:8080'], 
    requireHeader: ['origin', 'x-requested-with'],
    removeHeaders: ['cookie', 'cookie2']
}).listen(port, host, function() {
    console.log('Running CORS Anywhere on ' + host + ':' + port);
});

Solution

  • Instead of using basic auth you should consider building an atlassian connect add-on. You could use atlassian-connect-express to start with, it will handle installation of the add-on and validation of JWT tokens. Basically, you will be able to do secure calls from your server (signed with JWT tokens) or do calls to Jira API from your front-end (embedded inside Jira) that will be executed as a particular user, which will generate proper "updated by" entries.