diff --git a/.gitignore b/.gitignore
index 70544e84748b14340241f3491a6ffb100bcb7ebe..3847784e1f68d90e81d04b694f65123994ec7f10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ vendor/cache/
 config/database.yml
 .rvmrc_custom
 .rvmrc.local
+oidc_key.pem
 
 # Mailing list stuff
 config/email_offset
diff --git a/app/controllers/api/openid_connect/id_tokens_controller.rb b/app/controllers/api/openid_connect/id_tokens_controller.rb
index dae760892a34eb00506c33b4b5e7167cec99d740..9e8c65b89501cf272dbc46528d16a1fa8fe2566f 100644
--- a/app/controllers/api/openid_connect/id_tokens_controller.rb
+++ b/app/controllers/api/openid_connect/id_tokens_controller.rb
@@ -8,7 +8,7 @@ module Api
       private
 
       def build_jwk
-        JSON::JWK.new(Api::OpenidConnect::IdTokenConfig.public_key, use: :sig)
+        JSON::JWK.new(Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY, use: :sig)
       end
     end
   end
diff --git a/app/models/api/openid_connect/id_token.rb b/app/models/api/openid_connect/id_token.rb
index 2855a38b0aae1f94068dfcf92ce56963e70c2ff2..5acfa0ea4df410781637b76a94e1e6d0e65a75c0 100644
--- a/app/models/api/openid_connect/id_token.rb
+++ b/app/models/api/openid_connect/id_token.rb
@@ -12,7 +12,7 @@ module Api
       end
 
       def to_jwt(options={})
-        to_response_object(options).to_jwt OpenidConnect::IdTokenConfig.private_key
+        to_response_object(options).to_jwt OpenidConnect::IdTokenConfig::PRIVATE_KEY
       end
 
       def to_response_object(options={})
diff --git a/features/step_definitions/auth_code_steps.rb b/features/step_definitions/auth_code_steps.rb
index 36ea99cedde38e4e78cf92f73962ddce314e2d79..37b4f7b8bc6e1ef78d1e2430df4457fe8ff3f2d9 100644
--- a/features/step_definitions/auth_code_steps.rb
+++ b/features/step_definitions/auth_code_steps.rb
@@ -30,7 +30,7 @@ When /^I parse the tokens and use it obtain user info$/ do
   access_token = client_json["access_token"]
   encoded_id_token = client_json["id_token"]
   decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                Api::OpenidConnect::IdTokenConfig.public_key
+                                                                Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
   expect(decoded_token.sub).to eq(@me.diaspora_handle)
   get api_openid_connect_user_info_path, access_token: access_token
 end
diff --git a/lib/api/openid_connect/id_token_config.rb b/lib/api/openid_connect/id_token_config.rb
index d046d4b7a28dfda369bcdfd5004e9f30c4c7cc94..541fa466352368c85c91bd6c494dd8341bb0866a 100644
--- a/lib/api/openid_connect/id_token_config.rb
+++ b/lib/api/openid_connect/id_token_config.rb
@@ -1,13 +1,18 @@
 module Api
   module OpenidConnect
     class IdTokenConfig
-      @@key = OpenSSL::PKey::RSA.new(2048)
-      def self.public_key
-        @@key.public_key
-      end
-      def self.private_key
-        @@key
+      private_key = OpenSSL::PKey::RSA.new(2048)
+      key_file_path = File.join(Rails.root, "config", "oidc_key.pem")
+      if File.exist?(key_file_path)
+        private_key = OpenSSL::PKey::RSA.new(File.read(key_file_path))
+      else
+        open key_file_path, "w" do |io|
+          io.write private_key.to_pem
+        end
+        File.chmod(0600, key_file_path)
       end
+      PRIVATE_KEY = private_key
+      PUBLIC_KEY = private_key.public_key
     end
   end
 end
diff --git a/spec/controllers/api/openid_connect/authorizations_controller_spec.rb b/spec/controllers/api/openid_connect/authorizations_controller_spec.rb
index 244799a284b7b3037998429ba3e24332d1befb77..5233ef9762b798b9aafa10b5df6bf22d30437b20 100644
--- a/spec/controllers/api/openid_connect/authorizations_controller_spec.rb
+++ b/spec/controllers/api/openid_connect/authorizations_controller_spec.rb
@@ -146,7 +146,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
           expect(response.location).to have_content("id_token=")
           encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
           decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                        Api::OpenidConnect::IdTokenConfig.public_key
+                                                                        Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
           expect(decoded_token.nonce).to eq("4130930983")
           expect(decoded_token.exp).to be > Time.zone.now.utc.to_i
         end
@@ -164,7 +164,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
           expect(response.location).to have_content("id_token=")
           encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
           decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                        Api::OpenidConnect::IdTokenConfig.public_key
+                                                                        Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
           expect(decoded_token.nonce).to eq("4130930983")
           expect(decoded_token.exp).to be > Time.zone.now.utc.to_i
         end
@@ -196,7 +196,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
         it "should return the id token in a fragment" do
           encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
           decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                        Api::OpenidConnect::IdTokenConfig.public_key
+                                                                        Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
           expect(decoded_token.nonce).to eq("4180930983")
           expect(decoded_token.exp).to be > Time.zone.now.utc.to_i
         end
@@ -204,7 +204,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
         it "should return a valid access token in a fragment" do
           encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
           decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                        Api::OpenidConnect::IdTokenConfig.public_key
+                                                                        Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
           access_token = response.location[/(?<=access_token=)[^&]+/]
           access_token_check_num = UrlSafeBase64.encode64(OpenSSL::Digest::SHA256.digest(access_token)[0, 128 / 8])
           expect(decoded_token.at_hash).to eq(access_token_check_num)
@@ -227,7 +227,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
           expect(response.location).to have_content("id_token=")
           encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
           decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                        Api::OpenidConnect::IdTokenConfig.public_key
+                                                                        Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
           expect(decoded_token.nonce).to eq("4180930983")
           expect(decoded_token.exp).to be > Time.zone.now.utc.to_i
         end
diff --git a/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb b/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb
index 06930c45b3d3154233a788ab3f9e966f0dcd062d..6827863d5316dc39a1308f3f4d7a642b044eeda9 100644
--- a/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb
+++ b/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb
@@ -13,7 +13,7 @@ describe Api::OpenidConnect::IdTokensController, type: :controller do
         JSON::JWK.decode jwk
       end
       public_key = public_keys.first
-      expect(Api::OpenidConnect::IdTokenConfig.private_key.public_key.to_s).to eq(public_key.to_s)
+      expect(Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY.to_s).to eq(public_key.to_s)
     end
   end
 end
diff --git a/spec/lib/api/openid_connect/token_endpoint_spec.rb b/spec/lib/api/openid_connect/token_endpoint_spec.rb
index 1dad2c13368d0c64fa8edab85722a681d7c5b5e9..dfbee1eebb1da6140c1646425492594be0c74913 100644
--- a/spec/lib/api/openid_connect/token_endpoint_spec.rb
+++ b/spec/lib/api/openid_connect/token_endpoint_spec.rb
@@ -21,7 +21,7 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
         json = JSON.parse(response.body)
         encoded_id_token = json["id_token"]
         decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                      Api::OpenidConnect::IdTokenConfig.public_key
+                                                                      Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
         expected_guid = bob.pairwise_pseudonymous_identifiers.find_by(sector_identifier: "https://example.com/uri").guid
         expect(decoded_token.sub).to eq(expected_guid)
         expect(decoded_token.exp).to be > Time.zone.now.utc.to_i
@@ -31,7 +31,7 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
         json = JSON.parse(response.body)
         encoded_id_token = json["id_token"]
         decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
-                                                                      Api::OpenidConnect::IdTokenConfig.public_key
+                                                                      Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY
         access_token = json["access_token"]
         access_token_check_num = UrlSafeBase64.encode64(OpenSSL::Digest::SHA256.digest(access_token)[0, 128 / 8])
         expect(decoded_token.at_hash).to eq(access_token_check_num)