Spotify API bad request on api/token authorization Error: 400

江枫思渺然 提交于 2019-12-13 04:12:34

问题


I am trying to authorize spotify api requests using Client Credentials Flow on the Spotify API Docs page. Here is my code in javascript ES6 format using the fetch API

    const response = await fetch('https://accounts.spotify.com/api/token', {
    mode: 'no-cors',
    method: 'POST',
    headers: {
      'Authorization': 'Basic Yzg4OWYzMjM5MjI0NGM4MGIyMzIyOTI5ODQ2ZjZmZWQ6MmUzZTM2YTMzMTM5NDM1Mzk3NzM4ZDMxMTg4MzM0Mjc=',
      'Content-type': 'application/x-www-form-urlencoded'
      },
    body: 'grant_type=client_credentials'
});

The console is saying it is a bad request and doesn't return any JSON.

Another thing that really confuses me is that when I send the request using POSTMAN with those headers and that body, it returns exactly what I want (It works) I don't see how this is different from what I'm doing...? Could anyone please help?

Also here is the code from postman in Javascript Jquery Ajax if this helpls:

var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://accounts.spotify.com/api/token",
  "method": "POST",
  "headers": {
    "Authorization": "Basic Yzg4OWYzMjM5MjI0NGM4MGIyMzIyOTI5ODQ2ZjZmZWQ6MmUzZTM2YTMzMTM5NDM1Mzk3NzM4ZDMxMTg4MzM0Mjc=",
    "Content-Type": "application/x-www-form-urlencoded",
    "Cache-Control": "no-cache",
    "Postman-Token": "2f93918d-2e8e-4fb0-a168-7e153dd83912"
  },
  "data": {
    "grant_type": "client_credentials"
  }
}  

$.ajax(settings).done(function (response) {
  console.log(response);
});

This is what the request looks like in DevTools


回答1:


That particular endpoint is not meant to be consumed client side. You are supposed to use it in some server side script.

https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow

The Client Credentials flow is used in server-to-server authentication

Another hint that it is meant to be server side only is that it uses your client secret as its name implies it is meant to be kept secret and having it viewable on the client isn't very secret.

So from that endpoint you get the access token which you can then use on the client side to make requests to the other api endpoints like https://api.spotify.com/v1/tracks

Now as for why it doesn't work in your calls. It works in postman because it ignores CORS, and it properly sends the authorization header. In the browser however you set the fetch() request mode to no-cors. In this mode only certain headers can be sent AND the response back cannot be read by javascript.

Due to this your request does not send the authorization header as it is not one of the simple headers allowed in no-cors mode. And so your request fails. Even if the authorization went through you wouldn't have been able to read the response anyways as per no-cors rules.

So if you want to continue using the Client Credentials flow you would:

  1. From the browser, make a request to your own server.

    fetch("http://myserver.com/getToken")
    
  2. On the server you would then do the https://accounts.spotify.com/api/token request from there sending all the correct information. Then send the returned access token back to the client

    //this is assuming a nodejs server environment
    var postQuery = 'grant_type=client_credentials ';
    var request = require('request');
    var express = require('express');
    var app = express();
    app.get('/getToken', function(req, res){
      request({
        url: "https://accounts.spotify.com/api/token",
        method: "POST",
        headers: {
          'Authorization': 'Basic YourBase64EncodedCredentials',
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': postQuery.length
        },
        body: postQuery
      }, function (error, response, data){
        //send the access token back to client
        res.end(data);
      });    
    });
    
  3. Use that access token in a normal fetch request to the endpoints you need to use as they are setup with the proper CORS headers

    fetch("http://myserver.com/getToken")
    .then(token=>{
      //token will be the token returned from your own server side script
      //now we can make a new request to the tracks (or any other api)
      return fetch("https://api.spotify.com/v1/tracks",{
        headers:{
          'Authorization': `Bearer ${token}`
        }
      }).then(r=>r.json())
    })
    .then(data=>{
       //data will be the data returned from tracks api endpoint
     });
    


来源:https://stackoverflow.com/questions/53218678/spotify-api-bad-request-on-api-token-authorization-error-400

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!