mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-04-07 07:36:58 +00:00
Verify token signature for authenticated login
We were just logging in any user without password or other verification before. Now we verify the Keycloak signature and know that the person is indeed logged in.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user