Compare commits

...
2 changed files with 45 additions and 3 deletions
+26 -1
View File
@@ -1,5 +1,30 @@
module HmacConcern
def hmac_verified?
ActiveModel::Type::Boolean.new.cast(params[:hmac_verified]).present?
return false unless hmac_verification_params_valid?
expected_hash = OpenSSL::HMAC.hexdigest(
'sha256',
hmac_channel.hmac_token,
@contact.identifier
)
identifier_hash = params[:identifier_hash].to_s
return false unless identifier_hash.bytesize == expected_hash.bytesize
ActiveSupport::SecurityUtils.secure_compare(identifier_hash, expected_hash)
end
private
def hmac_verification_params_valid?
params[:identifier_hash].present? &&
@contact&.identifier.present? &&
params[:identifier].to_s == @contact.identifier &&
hmac_channel.present?
end
def hmac_channel
return if @inbox.blank?
@hmac_channel ||= @inbox.channel if @inbox.channel.respond_to?(:hmac_token)
end
end
@@ -2,7 +2,7 @@ require 'rails_helper'
RSpec.describe '/api/v1/accounts/{account.id}/contacts/:id/contact_inboxes', type: :request do
let(:account) { create(:account) }
let(:contact) { create(:contact, account: account, email: 'f.o.o.b.a.r@gmail.com') }
let(:contact) { create(:contact, account: account, email: 'f.o.o.b.a.r@gmail.com', identifier: 'contact-identifier') }
let(:channel_twilio_sms) { create(:channel_twilio_sms, account: account) }
let(:channel_email) { create(:channel_email, account: account) }
let(:channel_api) { create(:channel_api, account: account) }
@@ -45,7 +45,7 @@ RSpec.describe '/api/v1/accounts/{account.id}/contacts/:id/contact_inboxes', typ
expect(contact.reload.contact_inboxes.map(&:inbox_id)).to include(channel_email.inbox.id)
end
it 'creates an hmac verified contact inbox' do
it 'does not trust client supplied hmac_verified param' do
create(:inbox_member, inbox: channel_api.inbox, user: agent)
expect do
post "/api/v1/accounts/#{account.id}/contacts/#{contact.id}/contact_inboxes",
@@ -54,6 +54,23 @@ RSpec.describe '/api/v1/accounts/{account.id}/contacts/:id/contact_inboxes', typ
as: :json
end.to change(ContactInbox, :count).by(1)
expect(response).to have_http_status(:success)
contact_inbox = contact.reload.contact_inboxes.find_by(inbox_id: channel_api.inbox.id)
expect(contact_inbox).to be_present
expect(contact_inbox.hmac_verified).to be(false)
end
it 'creates an hmac verified contact inbox with a valid identifier hash' do
create(:inbox_member, inbox: channel_api.inbox, user: agent)
identifier_hash = OpenSSL::HMAC.hexdigest('sha256', channel_api.hmac_token, contact.identifier)
expect do
post "/api/v1/accounts/#{account.id}/contacts/#{contact.id}/contact_inboxes",
params: { inbox_id: channel_api.inbox.id, identifier: contact.identifier, identifier_hash: identifier_hash },
headers: agent.create_new_auth_token,
as: :json
end.to change(ContactInbox, :count).by(1)
expect(response).to have_http_status(:success)
contact_inbox = contact.reload.contact_inboxes.find_by(inbox_id: channel_api.inbox.id)
expect(contact_inbox).to be_present