From ac4d9022db34c5174efc3b3ccf8879154af7bfa0 Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Thu, 5 Dec 2019 14:02:25 +0000 Subject: [PATCH 1/4] Add service that generates Base(58) secure tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In WEX and FRAE we have relied on using [HasSecureToken](https://github.com/robertomiranda/has_secure_token) to generate unique random tokens of a fixed length in the objects we create. We have a need to unqiuely identify a record, but cannot use its ID because it also has to be something 'unguessable'. HasSecureToken works for WEX and FRAE because it is designed to work with ActiveRecord models. WCR on the overhand uses MongoDb, which means we can't use it. So instead, we've copied it wholesale into our project as a service we can call when we need to generate a token. Thanks @robertomiranda 😁! --- .../secure_token_service.rb | 31 ++++++++++++++++ .../secure_token_service_spec.rb | 36 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 app/services/waste_carriers_engine/secure_token_service.rb create mode 100644 spec/services/waste_carriers_engine/secure_token_service_spec.rb diff --git a/app/services/waste_carriers_engine/secure_token_service.rb b/app/services/waste_carriers_engine/secure_token_service.rb new file mode 100644 index 000000000..d181f9cc1 --- /dev/null +++ b/app/services/waste_carriers_engine/secure_token_service.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "securerandom" + +module WasteCarriersEngine + + # SecureTokenService generates a random base58 string of length 24. + # + # SecureRandom::base58 is used to generate the 24-character unique tokens, so + # collisions are highly unlikely. + # + # The result will contain only alphanumeric characters except 0, O, I and l + # + # p SecureRandom.base58 #=> "4kUgL2pdQMSCQtjE" + # p SecureRandom.base58(24) #=> "77TMHrHJFvFDwodq8w7Ev2m7" + # + # Copied almost verbatim from + # https://github.com/robertomiranda/has_secure_token + class SecureTokenService < BaseService + BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - %w[0 O I l] + + def run + SecureRandom.random_bytes(24).unpack("C*").map do |byte| + idx = byte % 64 + idx = SecureRandom.random_number(58) if idx >= 58 + BASE58_ALPHABET[idx] + end.join + end + + end +end diff --git a/spec/services/waste_carriers_engine/secure_token_service_spec.rb b/spec/services/waste_carriers_engine/secure_token_service_spec.rb new file mode 100644 index 000000000..025b285c5 --- /dev/null +++ b/spec/services/waste_carriers_engine/secure_token_service_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require "rails_helper" + +module WasteCarriersEngine + RSpec.describe SecureTokenService do + + describe ".run" do + context "the return value" do + it "is a string" do + expect(described_class.run).to be_a(String) + end + + it "is 24 characters in length" do + expect(described_class.run.length).to eq(24) + end + + it "contains only alphanumeric characters except 0, O, I and l" do + expect(described_class.run).to match(/^[a-km-zA-HJ-NP-Z1-9]*$/) + end + end + + it "generates a different result each time its called" do + results = [] + 10.times do + latest = described_class.run + + expect(results).not_to include(latest) + + results.push(latest) + end + end + end + + end +end From 829898dd4919ebe5ac0416110df6167fee17112c Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Thu, 5 Dec 2019 14:16:34 +0000 Subject: [PATCH 2/4] Typo --- .../services/waste_carriers_engine/secure_token_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/waste_carriers_engine/secure_token_service_spec.rb b/spec/services/waste_carriers_engine/secure_token_service_spec.rb index 025b285c5..d64ab016c 100644 --- a/spec/services/waste_carriers_engine/secure_token_service_spec.rb +++ b/spec/services/waste_carriers_engine/secure_token_service_spec.rb @@ -20,7 +20,7 @@ module WasteCarriersEngine end end - it "generates a different result each time its called" do + it "generates a different result each time it is called" do results = [] 10.times do latest = described_class.run From 90ffeb55ae97b0fbe6c79b7ae99bf53f4f998bbd Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Thu, 5 Dec 2019 14:23:20 +0000 Subject: [PATCH 3/4] Remove a line break Because whitespace slows @cintamini down! Co-Authored-By: cintamani --- app/services/waste_carriers_engine/secure_token_service.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/services/waste_carriers_engine/secure_token_service.rb b/app/services/waste_carriers_engine/secure_token_service.rb index d181f9cc1..283dac1f2 100644 --- a/app/services/waste_carriers_engine/secure_token_service.rb +++ b/app/services/waste_carriers_engine/secure_token_service.rb @@ -3,7 +3,6 @@ require "securerandom" module WasteCarriersEngine - # SecureTokenService generates a random base58 string of length 24. # # SecureRandom::base58 is used to generate the 24-character unique tokens, so From 5dc161422ba834dc5d5612dd6edf18a34266909d Mon Sep 17 00:00:00 2001 From: Alan Cruikshanks Date: Thu, 5 Dec 2019 14:24:06 +0000 Subject: [PATCH 4/4] Remove line break Because white space slows @cintamani down! Co-Authored-By: cintamani --- spec/services/waste_carriers_engine/secure_token_service_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/services/waste_carriers_engine/secure_token_service_spec.rb b/spec/services/waste_carriers_engine/secure_token_service_spec.rb index d64ab016c..216ef07ff 100644 --- a/spec/services/waste_carriers_engine/secure_token_service_spec.rb +++ b/spec/services/waste_carriers_engine/secure_token_service_spec.rb @@ -31,6 +31,5 @@ module WasteCarriersEngine end end end - end end