Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions test/privy/integration/jwt_exchange_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class Privy::Test::Integration::JwtExchangeTest < Privy::Test::IntegrationTest
def setup
super
skip("JWT_AUTH_SK not set") unless ENV["JWT_AUTH_SK"] && !ENV["JWT_AUTH_SK"].empty?

# /wallets/authenticate (which jwt_exchange wraps) rejects JWTs for users
# that don't own any wallet. Ensure the freshly-minted user has one.
create_user_owned_wallet
end

def test_exchange_jwt_returns_authorization_key
Expand Down
3 changes: 1 addition & 2 deletions test/privy/integration/services/wallets_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ def test_raw_sign_on_p256_owned_wallet_returns_signature
def test_raw_sign_on_user_owned_wallet_returns_signature
skip("JWT_AUTH_SK not set") unless ENV["JWT_AUTH_SK"] && !ENV["JWT_AUTH_SK"].empty?

user = client.users.get_by_custom_auth_id(custom_user_id: jwt_auth_subject)
wallet = client.wallets.create(wallet_create_params: {chain_type: :tron, owner: {user_id: user.id}})
wallet = create_user_owned_wallet(chain_type: :tron)
jwt = generate_test_jwt

ctx = Privy::Authorization::AuthorizationContext.build(user_jwts: [jwt])
Expand Down
27 changes: 23 additions & 4 deletions test/privy/integration/support/jwt_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,45 @@

require "openssl"
require "jwt"
require "securerandom"

module Privy
module Test
module Integration
module JwtHelpers
# A unique custom-auth subject per test instance. Memoized so the JWT
# `sub` claim and the user's custom_auth_id stay in lockstep within one
# test, while Minitest's per-test instance gives us a fresh value across
# tests and runs. This avoids accumulating wallets under a single shared
# user (which trips the per-user wallet limit on staging).
def jwt_auth_subject
ENV.fetch("JWT_AUTH_SUBJECT", "java-sdk-sub-id")
@jwt_auth_subject ||= "ruby-sdk-test-#{SecureRandom.uuid}"
end

def generate_test_jwt
# Ensure the Privy user exists before handing out a JWT for them; the
# API endpoints that accept these JWTs (e.g. /wallets/authenticate)
# 404 when the subject has never been linked to a user.
jwt_auth_user
raw = ENV.fetch("JWT_AUTH_SK")
pem = raw.gsub('\n', "\n").gsub("\r", "").strip
private_key = OpenSSL::PKey::RSA.new(pem)
payload = {sub: jwt_auth_subject, exp: Time.now.to_i + 3600}
JWT.encode(payload, private_key, "RS256", {typ: "JWT"})
end

def create_user_owned_wallet
user = client.users.get_by_custom_auth_id(custom_user_id: jwt_auth_subject)
client.wallets.create(wallet_create_params: {chain_type: :ethereum, owner: {user_id: user.id}})
# Lazily creates a Privy user backed by a fresh custom-auth subject and
# returns it. Subsequent calls within the same test return the same user.
def jwt_auth_user
@jwt_auth_user ||= client.users.create(
linked_accounts: [{type: :custom_auth, custom_user_id: jwt_auth_subject}]
)
end

def create_user_owned_wallet(chain_type: :ethereum)
client.wallets.create(
wallet_create_params: {chain_type: chain_type, owner: {user_id: jwt_auth_user.id}}
)
end
end
end
Expand Down
Loading