ruby - 在 Ruby 中生成 JWT

标签 ruby jwt hmac

我正在尝试发布到 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": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="aec3cfdccdc6cbdceedec7c0c9cacbd8cbc2c1decbdcdd80cdc1c3" rel="noreferrer noopener nofollow">[email protected]</a>",
        "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]

当我将其与我自己的信息一起使用时,它会返回 403 错误。为了获取我正在使用的格式的时间戳:

timestamp = Time.now.utc.strftime("%m-%e-%y %H:%M:%S.000")

我做错了什么?

解决方案:

我能够使用此代码成功构建 token :

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 的 key ,您应该在其中使用二进制 key ,即首先对其进行 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]

关于ruby - 在 Ruby 中生成 JWT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35245067/

相关文章:

ruby-on-rails - Nginx + 乘客 : Multiple domains need to point to different root

ruby - ruby中定义的method_missing在哪里

ruby-on-rails - 错误 : File to import not found or unreadable: mycustom. scss。运行: rake Assets :预编译

json - JWT 是否共享/存储用于在客户端和服务器上签名的 secret ?

ios - 在 iOS/Objective-c Ruby/Rails 中匹配 Base64 编码的 HMAC-SHA1 字符串

python - R 与 Python 中的 HMAC 编码

ruby - 如何将参数传递给 RubyMine 3.0 中的 rake 任务?

ios - 为 Apple 的 DeviceCheck API 生成 JWT

c# - 如何在 Angular 中解码 JWE token

java - Shopify oauth 中的 HMAC-SHA256 问题(输出不匹配)