Spotify Web API: Basic authorization

I need to get an access token from Spotify Web API. Based on this documentation I wrote the following method:

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

and the following RSpec test:

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

It happens that when I run this test, generating this request (caught with 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"

I get

=> 400 BadRequest | application/json 131 bytes

And it seems it is really a bad request, because I see no sign of the grant_type => client_credentials. The documentaions says this is mandadory as a request body parameter.

I believe I am sending this the wrong way, but I don't know how to to it correctly.

I tried to use RestClient#post instead of RestClient::Request#execute, doing this:

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

but then I got:

RestClient::UnsupportedMediaType: 415 Unsupported Media Type

How may I send a request body parameter using RestClient gem?

Upvotes: 2

Views: 1729

Answers (2)

Anthony
Anthony

Reputation: 15967

The issue is the way Base64 is encoding the string which includes newlines that most OAuth2 providers don't accept. You can do this instead:

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}"})

According to this answer, new lines are added every 60 characters (that is news to me). You can use another method that does not include newlines such as strict_encode...

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

Upvotes: 3

SamHecquet
SamHecquet

Reputation: 1836

It's not exactly the answer you're looking for, but you should definitively take a look at this Ruby Library: rspotify. Spotify Oauthentication is very easy to do with it.

Upvotes: 1

Related Questions