在 Ruby 中生成 JWT
Generating a JWT in Ruby
我正在尝试 post Ping Identity 的 PingID API,它一直给我 403 无效签名。
我相当确定我正在正确编码 JSON 消息。我得到的 header 字符串与他们的示例数据相同,但我不确定我是否正确创建了 HMAC SHA256 签名。
我正在使用 the API walkthrough,我编写的代码是:
require 'json'
require 'base64'
require 'OpenSSL'
require 'rest-client'
use_base64_key = "JWC41crr322aUfdckVfJKHvGKNIPyAPGL7rMsTbzHlA="
jwtheader = {
"alg": "HS256",
"org_alias": "aaaaaaaa-a1b2-123a-b456-1234abcd5678",
"token": "1a2b3c4d5e6f"
}
jwtpayload = {
"reqHeader": {
"locale": "en",
"orgAlias": "aaaaaaaa-a1b2-123a-b456-1234abcd5678",
"secretKey": "1a2b3c4d5e6f",
"timestamp": "2015-09-03 11:57:25.229",
"version": "4.6"
},
"reqBody": {
"activateUser": false,
"email": "marcher@pingdevelopers.com",
"fName": "Meredith",
"lname": "Archer",
"username": "meredith",
"role": "REGULAR",
"clientData": nil
}
}
jwtheader64 = Base64.urlsafe_encode64(jwtheader.to_json).chomp[0...-1]
jwtpayload64 = Base64.urlsafe_encode64(jwtpayload.to_json).chomp[0...-1]
signeddata = jwtheader64 + "." + jwtpayload64
digest = OpenSSL::Digest.new('sha256')
instance = OpenSSL::HMAC.digest(digest, use_base64_key, signeddata)
signature = Base64.urlsafe_encode64(instance).chomp[0...-1]
当我将其与我自己的信息一起使用时,它 returns 出现 403 错误。要以我使用的格式获取时间戳:
timestamp = Time.now.utc.strftime("%m-%e-%y %H:%M:%S.000")
我做错了什么?
解决方案:
我能够使用此代码成功构建令牌:
require 'json'
require 'base64'
require 'OpenSSL'
require 'rest-client'
pidalg = "HS256"
pidorg = "aaaaaaaa-a1b2-123a-b456-1234abcd5678"
pidtok = "c9fed74c5c994509b849ff65adb367d1"
timestamp = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S.000")
uid = "meredith"
pidkey = "JWC41crr322aUfdckVfJKHvGKNIPyAPGL7rMsTbzHlA="
#jwt header
jwtheader = {
"alg": pidalg,
"org_alias": pidorg,
"token": pidtok
}
#jwt payload
jwtpayload = {
"reqHeader":{
"locale":"en",
"orgAlias":pidorg,
"secretKey":pidtok,
"timestamp":timestamp,
"version":"4.6"
},
"reqBody":{
"getSameDeviceUsers":false,
"userName":uid,
}
}
jwtheaderJSON = jwtheader.to_json
jwtheaderUTF = jwtheaderJSON.encode("UTF-8")
tokenheader = Base64.urlsafe_encode64(jwtheaderUTF)
puts tokenheader
jwtpayloadJSON = jwtpayload.to_json
jwtpayloadUTF = jwtpayloadJSON.encode("UTF-8")
tokenpayload = Base64.urlsafe_encode64(jwtpayloadUTF)
puts tokenpayload
signeddata = tokenheader + "." + tokenpayload
digest = OpenSSL::Digest.new('sha256')
bin_key = Base64.decode64(pidkey)
puts bin_key
instance = OpenSSL::HMAC.digest(digest, bin_key, signeddata)
signature = Base64.urlsafe_encode64(instance)
puts signature
apitoken = signeddata + "." + signature
puts apitoken
您的代码基本上是正确的,但是您使用 base64 编码的表示形式作为对 JWT 进行签名的密钥,您应该在其中使用二进制密钥,即首先对其进行 base64 解码,如下所示:
digest = OpenSSL::Digest.new('sha256')
bin_key = Base64.decode64(use_base64_key)
instance = OpenSSL::HMAC.digest(digest, bin_key, signeddata)
signature = Base64.urlsafe_encode64(instance).chomp[0...-1]
jwt
gem 可用于编码和解码 JWT 令牌
payload = { id: 1, email: 'user@example.com' }
secret = Rails.application.credentials.secret_key_base
token = JWT.encode(payload, secret, 'HS256')
我正在尝试 post Ping Identity 的 PingID API,它一直给我 403 无效签名。
我相当确定我正在正确编码 JSON 消息。我得到的 header 字符串与他们的示例数据相同,但我不确定我是否正确创建了 HMAC SHA256 签名。
我正在使用 the API walkthrough,我编写的代码是:
require 'json'
require 'base64'
require 'OpenSSL'
require 'rest-client'
use_base64_key = "JWC41crr322aUfdckVfJKHvGKNIPyAPGL7rMsTbzHlA="
jwtheader = {
"alg": "HS256",
"org_alias": "aaaaaaaa-a1b2-123a-b456-1234abcd5678",
"token": "1a2b3c4d5e6f"
}
jwtpayload = {
"reqHeader": {
"locale": "en",
"orgAlias": "aaaaaaaa-a1b2-123a-b456-1234abcd5678",
"secretKey": "1a2b3c4d5e6f",
"timestamp": "2015-09-03 11:57:25.229",
"version": "4.6"
},
"reqBody": {
"activateUser": false,
"email": "marcher@pingdevelopers.com",
"fName": "Meredith",
"lname": "Archer",
"username": "meredith",
"role": "REGULAR",
"clientData": nil
}
}
jwtheader64 = Base64.urlsafe_encode64(jwtheader.to_json).chomp[0...-1]
jwtpayload64 = Base64.urlsafe_encode64(jwtpayload.to_json).chomp[0...-1]
signeddata = jwtheader64 + "." + jwtpayload64
digest = OpenSSL::Digest.new('sha256')
instance = OpenSSL::HMAC.digest(digest, use_base64_key, signeddata)
signature = Base64.urlsafe_encode64(instance).chomp[0...-1]
当我将其与我自己的信息一起使用时,它 returns 出现 403 错误。要以我使用的格式获取时间戳:
timestamp = Time.now.utc.strftime("%m-%e-%y %H:%M:%S.000")
我做错了什么?
解决方案:
我能够使用此代码成功构建令牌:
require 'json'
require 'base64'
require 'OpenSSL'
require 'rest-client'
pidalg = "HS256"
pidorg = "aaaaaaaa-a1b2-123a-b456-1234abcd5678"
pidtok = "c9fed74c5c994509b849ff65adb367d1"
timestamp = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S.000")
uid = "meredith"
pidkey = "JWC41crr322aUfdckVfJKHvGKNIPyAPGL7rMsTbzHlA="
#jwt header
jwtheader = {
"alg": pidalg,
"org_alias": pidorg,
"token": pidtok
}
#jwt payload
jwtpayload = {
"reqHeader":{
"locale":"en",
"orgAlias":pidorg,
"secretKey":pidtok,
"timestamp":timestamp,
"version":"4.6"
},
"reqBody":{
"getSameDeviceUsers":false,
"userName":uid,
}
}
jwtheaderJSON = jwtheader.to_json
jwtheaderUTF = jwtheaderJSON.encode("UTF-8")
tokenheader = Base64.urlsafe_encode64(jwtheaderUTF)
puts tokenheader
jwtpayloadJSON = jwtpayload.to_json
jwtpayloadUTF = jwtpayloadJSON.encode("UTF-8")
tokenpayload = Base64.urlsafe_encode64(jwtpayloadUTF)
puts tokenpayload
signeddata = tokenheader + "." + tokenpayload
digest = OpenSSL::Digest.new('sha256')
bin_key = Base64.decode64(pidkey)
puts bin_key
instance = OpenSSL::HMAC.digest(digest, bin_key, signeddata)
signature = Base64.urlsafe_encode64(instance)
puts signature
apitoken = signeddata + "." + signature
puts apitoken
您的代码基本上是正确的,但是您使用 base64 编码的表示形式作为对 JWT 进行签名的密钥,您应该在其中使用二进制密钥,即首先对其进行 base64 解码,如下所示:
digest = OpenSSL::Digest.new('sha256')
bin_key = Base64.decode64(use_base64_key)
instance = OpenSSL::HMAC.digest(digest, bin_key, signeddata)
signature = Base64.urlsafe_encode64(instance).chomp[0...-1]
jwt
gem 可用于编码和解码 JWT 令牌
payload = { id: 1, email: 'user@example.com' }
secret = Rails.application.credentials.secret_key_base
token = JWT.encode(payload, secret, 'HS256')