diff --git a/app/services/vine_jwt_service.rb b/app/services/vine_jwt_service.rb new file mode 100644 index 0000000000..f65f04a7f6 --- /dev/null +++ b/app/services/vine_jwt_service.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class VineJwtService + ALGORITHM = "HS256" + ISSUER = "openfoodnetwork" + + def initialize(secret: ) + @secret = secret + end + + def generate_token + generation_time = Time.zone.now + payload = { + iss: ISSUER, + iat: generation_time.to_i, + exp: (generation_time + 1.minute).to_i, + } + + JWT.encode(payload, @secret, ALGORITHM) + end +end diff --git a/spec/services/vine_jwt_service_spec.rb b/spec/services/vine_jwt_service_spec.rb new file mode 100644 index 0000000000..204dede96c --- /dev/null +++ b/spec/services/vine_jwt_service_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe VineJwtService do + describe "#generate_token" do + subject { described_class.new(secret: vine_secret) } + let(:vine_secret) { "some_secret" } + + it "generate a jwt token" do + expect(subject.generate_token).to be_a String + end + + it "includes issuing body" do + token = subject.generate_token + + payload = decode(token, vine_secret) + + expect(payload["iss"]).to eq("openfoodnetwork") + end + + it "includes issuing time" do + generate_time = Time.zone.now + Timecop.freeze(generate_time) do + token = subject.generate_token + + payload = decode(token, vine_secret) + + expect(payload["iat"].to_i).to eq(generate_time.to_i) + end + end + + it "includes expirations time" do + generate_time = Time.zone.now + Timecop.freeze(generate_time) do + token = subject.generate_token + + payload = decode(token, vine_secret) + + expect(payload["exp"].to_i).to eq((generate_time + 1.minute).to_i) + end + end + end + + def decode(token, secret) + JWT.decode( + token, + secret, + true, { algorithm: "HS256" } + ).first + end +end