diff --git a/engines/dfc_provider/README.md b/engines/dfc_provider/README.md index 0b39158005..f3effcbaac 100644 --- a/engines/dfc_provider/README.md +++ b/engines/dfc_provider/README.md @@ -15,6 +15,12 @@ account with a trusted OIDC provider. Currently these are: But you can also authenticate with your OFN user login (session cookie) through your browser. +And you can also use your OFN API token in the HTTP header. For example: + +``` +X-Api-Token: d6ccf8685b8cd29b67ae6186e9ceb423bd2ac30b7c880223 +``` + ## API endpoints The API is under development and this list may be out of date. diff --git a/engines/dfc_provider/app/services/authorization_control.rb b/engines/dfc_provider/app/services/authorization_control.rb index dd9f3b045c..e2643b43fd 100644 --- a/engines/dfc_provider/app/services/authorization_control.rb +++ b/engines/dfc_provider/app/services/authorization_control.rb @@ -19,7 +19,7 @@ class AuthorizationControl end def user - oidc_user || ofn_user + oidc_user || ofn_api_user || ofn_user rescue JWT::ExpiredSignature nil end @@ -30,6 +30,10 @@ class AuthorizationControl find_ofn_user(decode_token) if access_token end + def ofn_api_user + Spree::User.find_by(spree_api_key: ofn_api_token) if ofn_api_token.present? + end + def ofn_user @request.env['warden']&.user end @@ -46,6 +50,10 @@ class AuthorizationControl @request.headers['Authorization'].to_s.split(' ').last end + def ofn_api_token + @request.headers["X-Api-Token"] + end + def find_ofn_user(payload) return if payload["email"].blank? diff --git a/engines/dfc_provider/spec/services/authorization_control_spec.rb b/engines/dfc_provider/spec/services/authorization_control_spec.rb index be6e3af441..88239f933e 100644 --- a/engines/dfc_provider/spec/services/authorization_control_spec.rb +++ b/engines/dfc_provider/spec/services/authorization_control_spec.rb @@ -12,7 +12,7 @@ describe AuthorizationControl do create(:oidc_user) # another user token = allow_token_for(email: user.email) - expect(auth(token).user).to eq user + expect(auth(oidc_token: token).user).to eq user end it "ignores blank email" do @@ -20,28 +20,56 @@ describe AuthorizationControl do create(:user, uid: "") token = allow_token_for(email: nil) - expect(auth(token).user).to eq nil + expect(auth(oidc_token: token).user).to eq nil end it "ignores non-existent user" do user token = allow_token_for(email: generate(:random_email)) - expect(auth(token).user).to eq nil + expect(auth(oidc_token: token).user).to eq nil end it "ignores expired signatures" do token = allow_token_for(exp: Time.now.to_i, email: user.email) - expect(auth(token).user).to eq nil + expect(auth(oidc_token: token).user).to eq nil end end - def auth(token) + describe "with OFN API token" do + it "finds the user of the API key" do + user.update!(spree_api_key: "1234") + + expect(auth(api_token: "1234").user).to eq user + end + + it "returns nil if the token doesn't match" do + user.update!(spree_api_key: "1234") + + expect(auth(api_token: "123").user).to eq nil + end + + it "ignores a missing token" do + user.update!(spree_api_key: nil) + + expect(auth(api_token: nil).user).to eq nil + end + + it "ignores empty tokens" do + user.update!(spree_api_key: "") + + expect(auth(api_token: "").user).to eq nil + end + end + + def auth(oidc_token: nil, api_token: nil) + headers = {} + headers["Authorization"] = "Bearer #{oidc_token}" if oidc_token + headers["X-Api-Token"] = api_token if api_token + described_class.new( - double(:request, - headers: { "Authorization" => "Bearer #{token}" }, - env: { 'warden' => nil }) + double(:request, headers:, env: { 'warden' => nil }) ) end end