如何使用 Spotify SDK 和 Swift 3 正确处理令牌刷新。错误代码 = 3840

Posted

技术标签:

【中文标题】如何使用 Spotify SDK 和 Swift 3 正确处理令牌刷新。错误代码 = 3840【英文标题】:How to properly handle token refresh with Spotify SDK and Swift 3. Error Code=3840 【发布时间】:2017-04-10 09:10:41 【问题描述】:

tl;dr 我正在接收:JSON text did not start with array or object and option to allow fragments not set.,如果我尝试接收令牌,No refresh token available in the session!,如果我尝试更新令牌。

我正在尝试在 Swift 3 中为 Objective-C Spotify ios SDK beta-25 设置令牌刷新。我正在使用 Heroku 服务器和 Spotify 提供的 Ruby 脚本,已更改为我的凭据。

require 'sinatra'
require 'net/http'
require 'net/https'
require 'base64'
require 'encrypted_strings'
require 'json'

CLIENT_ID = ENV['xxx']
CLIENT_SECRET = ENV['xxx']
ENCRYPTION_SECRET = ENV['xxx']
CLIENT_CALLBACK_URL = ENV['xxx://returnafterlogin']
AUTH_HEADER = "Basic " + Base64.strict_encode64(CLIENT_ID + ":" + CLIENT_SECRET)
SPOTIFY_ACCOUNTS_ENDPOINT = URI.parse("https://accounts.spotify.com")

get '/' do
"Working"    
end

post '/swap' do

    # This call takes a single POST parameter, "code", which
    # it combines with your client ID, secret and callback
    # URL to get an OAuth token from the Spotify Auth Service,
    # which it will pass back to the caller in a JSON payload.

    auth_code = params[:code]

    http = Net::HTTP.new(SPOTIFY_ACCOUNTS_ENDPOINT.host, SPOTIFY_ACCOUNTS_ENDPOINT.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new("/api/token")

    request.add_field("Authorization", AUTH_HEADER)

    request.form_data = 
        "grant_type" => "authorization_code",
        "redirect_uri" => CLIENT_CALLBACK_URL,
        "code" => auth_code
    

    response = http.request(request)

    # encrypt the refresh token before forwarding to the client
    if response.code.to_i == 200
        token_data = JSON.parse(response.body)
        refresh_token = token_data["refresh_token"]
        encrypted_token = refresh_token.encrypt(:symmetric, :password => ENCRYPTION_SECRET)
        token_data["refresh_token"] = encrypted_token
        response.body = JSON.dump(token_data)
    end

    status response.code.to_i
    return response.body
end

post '/refresh' do

    # Request a new access token using the POST:ed refresh token

    http = Net::HTTP.new(SPOTIFY_ACCOUNTS_ENDPOINT.host, SPOTIFY_ACCOUNTS_ENDPOINT.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new("/api/token")

    request.add_field("Authorization", AUTH_HEADER)

    encrypted_token = params[:refresh_token]
    refresh_token = encrypted_token.decrypt(:symmetric, :password => ENCRYPTION_SECRET)

    request.form_data = 
        "grant_type" => "refresh_token",
        "refresh_token" => refresh_token
    

    response = http.request(request)

    status response.code.to_i
    return response.body

end

设置者:

SPTAuth.defaultInstance().tokenSwapURL = URL(string: SpotifyCredentials.tokenSwapURLSwap)
SPTAuth.defaultInstance().tokenRefreshURL = URL(string: SpotifyCredentials.tokenSwapURLRefresh)

现在用户无法再登录,我收到顶部发布的错误消息。如果我要删除 tokenSwapURLtokenRefreshURL,一切都会恢复正常,但用户必须每 60 分钟重新验证一次。

如果我尝试使用已登录的用户刷新令牌,我会收到:

"No refresh token available in the session!"

if SPTAuth.defaultInstance().session != nil 
        print("needs login")
        SPTAuth.defaultInstance().renewSession(SPTAuth.defaultInstance().session, callback:  error, session in
            if error != nil 
                print("\(error?.localizedDescription)") // "No refresh token available in the session!"
                return
            
        )

我错过了什么?非常感谢您的帮助。

【问题讨论】:

我在使用 spotify API 你解决了吗?我有同样的问题。 嘿@MarkusJohansson 是的。查看我发布的答案 【参考方案1】:

我已经能够使用以下 Git 为 Spotify 创建令牌刷新服务:

https://github.com/adamontherun/SpotifyTokenRefresh

您需要做的就是按照 git 项目中 Heroku 链接的说明进行操作。

我曾尝试与该项目的作者取得联系,但他无法告诉我,为什么我的方法行不通,但他的方法行得通。我能留给你的只有这个有效的Deploy to Heroku 链接。

【讨论】:

我想扩展它,但我没有在 ruby​​ 中编程,所以我决定将一个服务放在一起,但使用Node.js:github.com/alfiedouglas0/spotify-token-refresh【参考方案2】:

简短的总结:假设您的 JSON 解析工作正常,问题是 JSON 格式错误(服务器端)。


JSON 文本没有以数组或对象开头,并且允许未设置片段的选项

可以被的JSONSerialization.jsonObject(with:options:) 抛出

来自data 中 JSON 数据的 Foundation 对象,或者

nil 如果发生错误

格式错误的 JSON » nil 而不是令牌 » 当前令牌被取消 » 结果:“用户无法再登录”

获取格式错误的 JSON 的可能解释包括:

这通常是因为一些警告消息从您的服务器中抛出而没有将其放入响应数组中。例如,在 php 中,一些“警告消息”不会在您的数组中捕获,因此当您最终使用“echo json_encode($RESPONSE_ARR)”时,它不是 JSON 格式。 — https://***.com/a/38680699/3419541

来自同一个 SO 页面:

您需要在 iOS 应用程序中对此进行调试。首先将数据转换为字符串并打印并检查它。如果字符串看起来没问题,则打印数据本身 - 有时人们设法添加 0 个字节或控制字符,或两个字节顺序标记或类似的东西,它们在字符串中不可见但不是合法的 JSON。 — https://***.com/a/38681179/3419541

【讨论】:

我试图按照你的回答,但我有点做不到,因为一切都在 spotify 框架中工作。我不处理任何类型的 JSON,如果我想在有或没有刷新服务和服务器 url 的情况下运行,我所做的只是获取 spotify API 的信息。字面意思就是这样。其他一切都由 spotify 处理。

以上是关于如何使用 Spotify SDK 和 Swift 3 正确处理令牌刷新。错误代码 = 3840的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3.0 中的 Spotify SDK:如何知道歌曲何时结束

Spotify iOS SDK Swift 显示所有 (!) 播放列表 (20+)

如何使用 Spotify API 和 Spotify SDK [关闭]

Spotify SDK Demo Swift 可以工作,但不能翻译为基于 Storyboard 的项目

无法播放歌曲 Spotify SDK

无法使用 Spotify iOS App Remote SDK 禁用自动播放