Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何创建用于Apple Music的JWT_Ruby_Jwt - Fatal编程技术网

Ruby 如何创建用于Apple Music的JWT

Ruby 如何创建用于Apple Music的JWT,ruby,jwt,Ruby,Jwt,我正在尝试创建一个开发者令牌,它是一个ES256 JWT,用于苹果音乐认证。() 我正在使用ruby和JWT gem,但是在创建令牌之后,我在使用Apple Music进行身份验证时遇到了401错误 require 'jwt' payload = {:iss => 'CapExdTeam', :iat => '1497335982', :exp => '1513112982'} priv = "-----BEGIN PRIVATE KEY-----

我正在尝试创建一个开发者令牌,它是一个ES256 JWT,用于苹果音乐认证。()

我正在使用ruby和JWT gem,但是在创建令牌之后,我在使用Apple Music进行身份验证时遇到了401错误

    require 'jwt'

    payload = {:iss => 'CapExdTeam', :iat => '1497335982', :exp => '1513112982'}

    priv = "-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgU208KCg/doqiSzsVF5sknVtYSgt8/3oiYGbvryIRrzSgCgYIKoZIzj0DAQehRANCAAQfrvDWizEnWAzB2Hx2r/NyvIBO6KGBDL7wkZoKnz4Sm4+1P1dhD9fVEhbsdoq9RKEf8dvzTOZMaC/iLqZFKSN6
-----END PRIVATE KEY-----"
    ecdsa_key = OpenSSL::PKey::EC.new(priv)

    token = JWT.encode payload, ecdsa_key, 'ES256', { :kid => "CapExedKid", :alg => "ES256" }
    puts token

    `curl -v -H 'Authorization: Bearer #{token}' "https://api.music.apple.com/v1/catalog/us/songs/203709340"

我使用示例私钥模拟429错误只是为了演示

我使用了这个脚本,它工作得非常好

这是一个有效的Ruby实现。使用您的keyId和teamId呼叫,提供对您的私钥文件的访问权,然后继续

class AppleMusic

    @auth_token
    @validity_start
    @validity_end


    def initialize(keyId, teamId, options ={})
      appleKeyId = keyId
      appleTeamId = teamId
      @validity_start = Time.now.to_i
      @validity_end = Time.now.to_i + 43200  # 12 hours in seconds...

      # Build up the headers
      header = {
          'typ' => 'JWT',           # MUST BE SPECIFIED...  Apple doesn't tell you this!
          'alg' => 'ES256',
          'kid' => appleKeyId
      }

      # Build up the payload
      body = {
          'iss' => appleTeamId,
          'iat' => @validity_start,
          'exp' => @validity_end
      }

      # This should be installed manually on the server somewhere
      # TODO:  Add some protection around the file's existance, set the name & location
      # as some type of configuration key.
      file = File.read('lib/assets/AuthKey_xxxxxxx.p8')
      key = OpenSSL::PKey::EC.new(file)
      key.check_key

      @auth_token = JWT.encode(body, key, 'ES256', header)
      @auth_token
    end

    def auth_token
      @auth_token
    end

    def auth_header
      "Bearer #{@auth_token}"
    end

    def validity_start
      @validity_start
    end

    def validity_end
      @validity_end
    end
 end

根据@DanDevine的回答,这里有一种更为Ruby/OO的方法:

require "openssl"

# Example: 
#
#  token = AppleMusic::Token.new(key_id: "...", team_id: "...", keyfile: File.new("lib/assets/AuthKey_xxxxxxx.p8"))
#  token.auth_token
#  token.auth_header
# 
module AppleMusic
  class Token
    attr_reader :key_id, :team_id, :keyfile

    # Keyfile should be an IO type that responds to `read`
    def initialize(key_id:, team_id:, keyfile:)
      @key_id = key_id
      @team_id = team_id
      @keyfile = keyfile
    end

    def auth_token
      @auth_token ||= fetch_auth_token
    end

    def auth_header
      "Bearer #{auth_token}"
    end

  protected

    def fetch_auth_token
      header = {
        typ: "JWT", # Must be specified; not in documentation
        alg: "ES256",
        kid: key_id
      }

      body = {
        iss: team_id,
        iat: Time.now.to_i,
        exp: Time.now.to_i + 43_200 # 12hrs
      }

      JWT.encode(body, auth_key, 'ES256', header)
    end

    def auth_key
      key = OpenSSL::PKey::EC.new(keyfile.read)
      key.check_key
      key
    end
  end
end

它现在也可以在纯雨燕

您首先必须使用创建MusicKit标识符和私钥。然后,可以使用纯Swift轻松创建令牌

这或多或少只是对SwiftJWT API的调用:

let teamId = "yourTeamID"
let keyId = "yourKeyID"
let keyFileUrl = URL(fileURLWithPath:"/pathToYour/key.p8")

struct MyClaims: Claims {
    let iss: String
    let iat: Date?
    let exp: Date?
}

let myHeader = Header(kid: keyId)
let myClaims = MyClaims(iss: teamId, iat: Date(), exp: Date() +  24 * 60 * 60)
var myJWT = SwiftJWT.JWT(header: myHeader, claims: myClaims)

let token = try! myJWT.sign(using: .es256(privateKey: try! String(contentsOf: keyFileUrl).data(using: .utf8)!))

我使用Swift软件包管理器创建了一个简单的示例和一个命令行工具:

有相同的问题我有几乎相同的代码。可能是exp字段的划时代时间设置错误。嘿,谢谢,伙计,我已经为此制定了一个解决方案好几天了,准备使用我们的一个开发人员技术代码级别支持,问问他们会怎么做。除了swift,我没有太多的经验,所以我对所有其他语言都失去了兴趣。再次感谢!!!真高兴:你对如何做到这一点的描述是简单、直接和有效的!在看到各种各样的选择后,这是多么令人愉快的事情啊。谢谢你们很多次。最初的问题(和我自己找到它)正在寻找一个Ruby解决方案。提供的链接是用Python编写的,效果很好……只需要一个Ruby解决方案。@DanDevine如果您确保
priv
iat
exp
kid
iss
都设置为正确的值,那么问题中的代码应该可以工作。我用自己的钥匙取得了成功,使用了
iat=(Time.now-1.minute)。到I
exp=iat+12.hours
Ok。。。我实际上已经完成了这项工作,需要同时调试这两个脚本。pythonjwt库将“typ”:“JWT”修饰符以静默方式添加到标题中。。。Ruby JWT库没有。如果您手动将'typ':'JWT'添加到头散列中,它将按预期工作。现在的问题是…哪一个库是正确的?我写了一个将MusicKit与RubyMoon结合使用的中级教程。我相信这个答案和@coreyward的JWT说明和代码。