diff --git a/engines/dfc_provider/app/services/dfc_provider/authorization_control.rb b/engines/dfc_provider/app/services/dfc_provider/authorization_control.rb index e6922490c7..a7da60984b 100644 --- a/engines/dfc_provider/app/services/dfc_provider/authorization_control.rb +++ b/engines/dfc_provider/app/services/dfc_provider/authorization_control.rb @@ -4,12 +4,25 @@ # It controls an OICD Access token and an enterprise. module DfcProvider class AuthorizationControl + # Copied from: https://login.lescommuns.org/auth/realms/data-food-consortium/ + LES_COMMUNES_PUBLIC_KEY = <<~KEY + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl68JGqAILFzoi/1+6siXXp2vylu+7mPjYKjKelTtHFYXWVkbmVptCsamHlY3jRhqSQYe6M1SKfw8D+uXrrWsWficYvpdlV44Vm7uETZOr1/XBOjpWOi1vLmBVtX6jFeqN1BxfE1PxLROAiGn+MeMg90AJKShD2c5RoNv26e20dgPhshRVFPUGru+0T1RoKyIa64z/qcTcTVD2V7KX+ANMweRODdoPAzQFGGjTnL1uUqIdUwSfHSpXYnKxXOsnPC3Mowkv8UIGWWDxS/yzhWc7sOk1NmC7pb+Cg7G8NKj+Pp9qQZnXF39Dg95ZsxJrl6fyPFvTo3zf9CPG/fUM1CkkwIDAQAB + -----END PUBLIC KEY----- + KEY + + def self.public_key + OpenSSL::PKey::RSA.new(LES_COMMUNES_PUBLIC_KEY) + end + def initialize(request) @request = request end def user oidc_user || ofn_user + rescue JWT::ExpiredSignature + nil end private @@ -23,7 +36,11 @@ module DfcProvider end def decode_token - JWT.decode(access_token, nil, false).first + JWT.decode( + access_token, + self.class.public_key, + true, { algorithm: "RS256" } + ).first end def access_token diff --git a/engines/dfc_provider/spec/services/authorization_control_spec.rb b/engines/dfc_provider/spec/services/authorization_control_spec.rb index 2880d964c0..4be4ca8bfc 100644 --- a/engines/dfc_provider/spec/services/authorization_control_spec.rb +++ b/engines/dfc_provider/spec/services/authorization_control_spec.rb @@ -1,13 +1,15 @@ # frozen_string_literal: true -require 'spec_helper' +require DfcProvider::Engine.root.join("spec/spec_helper") describe DfcProvider::AuthorizationControl do + include AuthorizationHelper + let(:user) { create(:user) } describe "with OIDC token" do it "finds a user" do - token = JWT.encode({ email: user.email }, nil) + token = allow_token_for(email: user.email) auth = described_class.new( double(:request, headers: { "Authorization" => "Bearer #{token}" }) @@ -15,5 +17,16 @@ describe DfcProvider::AuthorizationControl do expect(auth.user).to eq user end + + it "ignores expired signatures" do + token = allow_token_for(exp: Time.now.to_i, email: user.email) + + auth = described_class.new( + double(:request, + headers: { "Authorization" => "Bearer #{token}" }) + ) + + expect(auth.user).to eq nil + end end end diff --git a/engines/dfc_provider/spec/support/authorization_helper.rb b/engines/dfc_provider/spec/support/authorization_helper.rb index fb453c329e..f35e028f1a 100644 --- a/engines/dfc_provider/spec/support/authorization_helper.rb +++ b/engines/dfc_provider/spec/support/authorization_helper.rb @@ -2,7 +2,15 @@ module AuthorizationHelper def authorise(email) - token = JWT.encode({ email: email }, nil) + token = allow_token_for(email: email) request.headers["Authorization"] = "JWT #{token}" end + + def allow_token_for(payload) + private_key = OpenSSL::PKey::RSA.generate 2048 + allow(DfcProvider::AuthorizationControl).to receive(:public_key). + and_return(private_key.public_key) + + JWT.encode(payload, private_key, "RS256") + end end