Spotify Web API:基本授权

Spotify Web API: Basic authorization

我需要从 Spotify Web API 获取访问令牌。基于this documentation我写了如下方法:

def authorize
  grant = Base64.encode64("#{SPOTIFY_KEY}:#{SPOTIFY_SECRET}")
  RestClient::Request.execute(
    method: :post,
    url: 'https://accounts.spotify.com/api/token',
    params: {'grant_type' => 'client_credentials'},
    headers: {"Authorization" => "Basic #{grant}","Accept" => "*/*; q=0.5, application/json"}
  )
end

和以下 RSpec 测试:

it 'authorize' do
  obj = SpotifyIntegration.new
  response = obj.authorize
  myjson = JSON.parse(response.body)
  expect(myjson.has_key?('access_token')).to be(true)
  expect(myjson.has_key?('token_type')).to be(true)
  expect(myjson['token_type']).to eq('bearer')
  expect(myjson.has_key?('expires_in')).to be(true)
end

碰巧当我 运行 这个测试时,生成这个请求(用 RESTCLIENT_LOG=stdout 捕获)

RestClient.post "https://accounts.spotify.com/api/token", "Accept"=>"/; q=0.5, application/json", "Accept-Encoding"=>"gzip, deflate", "Authorization"=>"Basic Y2NmNTI3ODVlZWI1NDVlODk0ZmM2ZTY3YTZhNDM0ZDA6YTQ5MjdlOGFmOWQy\nNGE0OTgyZDRkODI1MmJhZjBkNTI=\n"

我明白了

=> 400 BadRequest | application/json 131 bytes

看来这确实是一个糟糕的请求,因为我没有看到 grant_type => client_credentials 的迹象。文档说这是强制性的作为请求正文参数

我想我发送的方式有误,但我不知道如何正确发送。

我尝试使用 RestClient#post 而不是 RestClient::Request#execute,这样做:

def authorize
  grant = Base64.encode64("#{SPOTIFY_KEY}:#{SPOTIFY_SECRET}")
  RestClient.post 'https://accounts.spotify.com/api/token', {'grant_type' => 'client_credentials'}.to_json, {"Authentication" => "Basic #{grant}",content_type: :json, accept: :json}
end

但后来我得到了:

RestClient::UnsupportedMediaType: 415 Unsupported Media Type

如何使用 RestClient gem 发送请求正文参数?

这不是您要找的答案,但您绝对应该看看这个 Ruby 库:rspotify。 Spotify Oauthentication 很容易做到。

问题在于 Base64 编码字符串的方式,其中包含大多数 OAuth2 提供商不接受的换行符。您可以这样做:

grant = Base64.encode64("#{client_id}:#{client_secret}").delete("\n")

resp = RestClient.post('https://accounts.spotify.com/api/token',
                       {'grant_type' => 'client_credentials'},
                       {"Authorization" => "Basic #{grant}"})

根据 this 的回答,每 60 个字符添加新行(这对我来说是新闻)。您可以使用另一种不包含换行符的方法,例如 strict_encode...

grant = Base64.strict_encode64("#{client_id}:#{client_secret}")