From 4bc1fa669fd19a1e422927596b9c6711f8f93b68 Mon Sep 17 00:00:00 2001 From: Nick DeSteffen Date: Wed, 18 Dec 2024 09:01:12 -0600 Subject: [PATCH] Adding support for including optional channel_id and request_ip claims in Customer login JWT payload --- lib/bigcommerce/resources/customers/customer.rb | 7 ++++++- .../unit/resources/customers/customer_spec.rb | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/bigcommerce/resources/customers/customer.rb b/lib/bigcommerce/resources/customers/customer.rb index a9b7ba9..250cce7 100644 --- a/lib/bigcommerce/resources/customers/customer.rb +++ b/lib/bigcommerce/resources/customers/customer.rb @@ -11,6 +11,8 @@ module Bigcommerce class Customer < Resource include Bigcommerce::ResourceActions.new uri: 'customers/%d' + PERMITTED_OPTIONAL_CLAIMS = %w[channel_id request_ip].freeze + property :id property :_authentication property :count @@ -37,7 +39,7 @@ def self.count(params = {}) # Generate a token that can be used to log the customer into the storefront. # This requires your app to have the store_v2_customers_login scope and to # be installed in the store. - def login_token(config: Bigcommerce.config, redirect_to: '/') + def login_token(config: Bigcommerce.config, redirect_to: '/', optional_claims: {}) payload = { 'iss' => config.client_id, 'iat' => Time.now.to_i, @@ -48,6 +50,9 @@ def login_token(config: Bigcommerce.config, redirect_to: '/') 'redirect_to' => redirect_to } + optional_claims = optional_claims.slice(*PERMITTED_OPTIONAL_CLAIMS) + payload.merge!(optional_claims) if optional_claims.any? + JWT.encode(payload, config.client_secret, 'HS256', { typ: 'JWT' }) end end diff --git a/spec/bigcommerce/unit/resources/customers/customer_spec.rb b/spec/bigcommerce/unit/resources/customers/customer_spec.rb index 34c5534..2eec950 100644 --- a/spec/bigcommerce/unit/resources/customers/customer_spec.rb +++ b/spec/bigcommerce/unit/resources/customers/customer_spec.rb @@ -33,5 +33,18 @@ expect(payload['iat']).to be <= Time.now.to_i expect(payload['jti']).to_not be_empty end + context 'optional keys are included with the JWT is present' do + let(:channel_id) { String(Random.rand(1000)) } + let(:request_ip) { '127.0.0.1' } + + subject { customer.login_token(optional_claims: { 'channel_id' => channel_id, 'request_ip' => request_ip, 'bogus' => 'claim' }) } + + it 'encodes the JWT with optional claims' do + payload = JWT.decode(subject, client_secret, true, { :algorithm => 'HS256' })[0] + expect(payload['channel_id']).to eq(channel_id) + expect(payload['request_ip']).to eq(request_ip) + expect(payload['bogus']).to be_nil + end + end end end