Skip to content

Commit 46b8549

Browse files
committed
Generate JWK for One Login public key
As part of the omniauth initializer, resolve the public key from the private key and convert it to JWK format. Store this on the application config so that we can retrieve it later when we need to serve it from the JWKS endpoint. Set the JWK kid on the omniauth configuration so it is sent with requests to One Login.
1 parent 3138cd0 commit 46b8549

2 files changed

Lines changed: 64 additions & 1 deletion

File tree

config/initializers/omniauth.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
private_key_pem = private_key_pem.gsub('\n', "\n")
88

99
private_key = OpenSSL::PKey::RSA.new(private_key_pem)
10+
11+
public_key_jwk = JWT::JWK.new(private_key.public_key, use: "sig")
12+
Rails.application.config.x.one_login.public_key_jwk = public_key_jwk
1013
end
1114

1215
Rails.application.config.middleware.use OmniAuth::Builder do
@@ -16,7 +19,7 @@
1619
idp_base_url: Settings.govuk_one_login.base_url,
1720
private_key: private_key,
1821
redirect_uri: "/auth/govuk_one_login/callback",
19-
private_key_kid: "", # TODO: we'll need to set this when we switch to using a JWKS endpoint
22+
private_key_kid: public_key_jwk&.kid,
2023
signing_algorithm: "ES256",
2124
scope: "openid email",
2225
ui_locales: "en cy",

spec/initializers/omniauth_spec.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
require "rails_helper"
2+
3+
RSpec.describe "omniauth initializer" do
4+
let(:initializer_path) { Rails.root.join("config/initializers/omniauth.rb") }
5+
6+
let(:one_login_settings) do
7+
double(
8+
private_key: private_key_setting,
9+
client_id: "test-client-id",
10+
base_url: "https://oidc.integration.account.gov.uk",
11+
)
12+
end
13+
14+
before do
15+
allow(Settings).to receive(:govuk_one_login).and_return(one_login_settings)
16+
allow(Rails.application.config.middleware).to receive(:use)
17+
allow(OmniAuth::GovukOneLogin::IdpConfiguration).to receive(:new).and_return(instance_double(OmniAuth::GovukOneLogin::IdpConfiguration))
18+
end
19+
20+
around do |example|
21+
original_public_key_jwk = Rails.application.config.x.one_login.public_key_jwk
22+
original_idp_configuration = Rails.application.config.x.one_login.idp_configuration
23+
example.run
24+
ensure
25+
Rails.application.config.x.one_login.public_key_jwk = original_public_key_jwk
26+
Rails.application.config.x.one_login.idp_configuration = original_idp_configuration
27+
end
28+
29+
context "when the private key is present" do
30+
let(:rsa_private_key) { OpenSSL::PKey::RSA.generate(2048) }
31+
let(:private_key_setting) { Base64.encode64(rsa_private_key.to_pem) }
32+
33+
before { load initializer_path }
34+
35+
it "sets Rails.application.config.x.one_login.public_key_jwk" do
36+
expect(Rails.application.config.x.one_login.public_key_jwk).to be_a(JWT::JWK::RSA)
37+
end
38+
39+
it "sets the JWK use to 'sig'" do
40+
expect(Rails.application.config.x.one_login.public_key_jwk[:use]).to eq("sig")
41+
end
42+
43+
it "sets the JWK kid" do
44+
expect(Rails.application.config.x.one_login.public_key_jwk.kid).to be_a(String)
45+
end
46+
end
47+
48+
context "when the private key is absent" do
49+
let(:private_key_setting) { nil }
50+
51+
before do
52+
Rails.application.config.x.one_login.public_key_jwk = nil
53+
load initializer_path
54+
end
55+
56+
it "does not set Rails.application.config.x.one_login.public_key_jwk" do
57+
expect(Rails.application.config.x.one_login.public_key_jwk).to be_nil
58+
end
59+
end
60+
end

0 commit comments

Comments
 (0)