2

I'm building an app with Capacitor JS & Nuxt JS to interface with the Slack API so that I can set my Slack status, I've created a Slack App and have a xoxp- token which works just fine when I hit the endpoint with a POST request via Postman, but from my browser (localhost) and from the running app on my phone I'm getting the following CORS error:

Access to XMLHttpRequest at 'https://slack.com/api/users.profile.set' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

Now this seems silly because you must use the authorization header to provide the Bearer token for authentication, but even after temporarily omitting this, the CORS error remains.

I'm trying to POST to the endpoint for users.profile.set View another method

What am I missing in my Axios code?

setSlackStatusWithReminder (title, expiry) {
  const body = this.convertToQueryString({
    profile: this.convertToQueryString(this.profile),
    token: 'xoxp-mytoken'
  })

  this.$axios.post('https://slack.com/api/users.profile.set', body, {
    timeout: 10000,
    transformRequest(data, headers) {
      delete headers.common['Content-Type'];
      return data;
    }
  }).then(res => {
    console.log(res)

    if (res.data.ok != true) {
      alert('something went wrong with the .then')
    }

    this.isSettingStatus = false
    this.actions.isShown = false
  }).catch(err => {
    this.isSettingStatus = false
    this.actions.isShown = false
  })
},

UPDATE

I've got a function to convert my request body into a query string from my data, which looks like:

export default {
  data () {
    return {
      profile: {
        status_text: '',
        status_emoji: '',
        status_expiration: 0
      }
    }
  }
}

Query string function to convert body

convertToQueryString (obj) {
  const convert = Object.keys(obj)
                         .map((key, index) => `${key}=${encodeURIComponent(obj[key])}`)
                         .join('&')

  return convert
},

And I'm building it up like:

const body = this.convertToQueryString({
        profile: this.convertToQueryString(this.profile),
        token: 'xoxp-mytoken'
      })

It's giving me an invalid_profile response.

1
  • 1
    I really don't think slack-api is intended to be accessed from browser) Maybe there are some cors options in api settings but I doubt that. Commented Jul 12, 2021 at 15:10

2 Answers 2

4

Slack doesn't respond to the pre-flight OPTIONS request with a compatible response.

Avoid the preflight check entirely by ensuring it matches the requirements to be handled as a so-called "simple request".

Notably, ensure the content-type is application/x-www-form-urlencoded, serialize the request body to match and do not use the Authorization header to pass your bearer token, instead pass it as an argument in your request (token).

Sign up to request clarification or add additional context in comments.

7 Comments

So how would I put my code above into practive, I've just tried setting the Content-Type to application/x-www-form-urlencoded, and can't see where-else to pass the token since the docs doesn't have an example in JS here
The docs says to transmit the token in the header
Okay, so after sending the token as a token param in the body, I get a Content-Type CORS error telling me I'm not allowed this, so I delete that with: transformRequest(data, headers) { delete headers.common['Content-Type']; return data; } and I get a response telling me that my data is in an invalid format, because it's now missing a content type, I tried JSON.stringify() for my body too.
@RyanH as I mentioned in my answer, you need to url-encode the request body. Here is an example of that from the axios docs.
|
4

Not sure why this was so difficult, the following is a valid POST request to the Slack API:

// this.profile -> is the object with the status_* fields
const body = `profile=${JSON.stringify(this.profile)}&token=some_token`

this.$axios.post('https://slack.com/api/users.profile.set', body, {
  timeout: 10000,
  transformRequest(data, headers) {
    delete headers.common['Content-Type'];
    return data;
  }
}).then(res => {
  console.log(err)
}).catch(err => {
  console.log(err)
})

1 Comment

Thanks, it worked. The token=${access_token} did the trick for me: ts const response = await axios.post( "https://slack.com/api/auth.test", `token=${access_token}`, );

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.