Repository: rails/rails
File: railties/test/application/configuration_test.rb (Ruby)

Code before:
      assert signed_id_verifier.verify(signed_account_id_one_with_new_options, purpose: "account")
    end

    test "Rails.application.message_verifiers['active_record/signed_id'] verifies messages using legacy options when config.active_record.use_legacy_signed_id_verifier is :verify" do
      add_to_config <<-RUBY
        config.active_record.use_legacy_signed_id_verifier = :verify
        config.secret_key_base = "secret"
      RUBY

      app "development"

      signed_id_verifier = ActiveRecord.message_verifiers["active_record/signed_id"]

      # generate with new options
      signed_account_id_one = signed_id_verifier.generate(1, purpose: "account")
      expected_signed_account_id_one =
        ActiveSupport::MessageVerifier.new(app.key_generator("secret").generate_key("active_record/signed_id"))
          .generate(1, purpose: "account")

      assert_equal expected_signed_account_id_one, signed_account_id_one

      # verify with legacy options
      signed_account_id_one_with_legacy_options =
        ActiveSupport::MessageVerifier.new(app.key_generator("secret").generate_key("active_record/signed_id"), digest: "SHA256", serializer: JSON, url_safe: true)
          .generate(1, purpose: "account")
      assert signed_id_verifier.verify(signed_account_id_one_with_legacy_options, purpose: "account")
    end

    test "Rails.application.message_verifiers['active_record/signed_id'] does not use legacy options when config.active_record.use_legacy_signed_id_verifier is false" do
      add_to_config <<-RUBY
        config.active_record.use_legacy_signed_id_verifier = false
        config.secret_key_base = "secret"
      RUBY

      app "development"

      signed_id_verifier = ActiveRecord.message_verifiers["active_record/signed_id"]

      # generate with new options
      signed_account_id_one = signed_id_verifier.generate(1, purpose: "account")
      expected_signed_account_id_one =
        ActiveSupport::MessageVerifier.new(app.key_generator("secret").generate_key("active_record/signed_id"))
          .generate(1, purpose: "account")

      assert_equal expected_signed_account_id_one, signed_account_id_one

      # not verify with legacy options
      signed_account_id_one_with_legacy_options =
      ActiveSupport::MessageVerifier.new(app.key_generator("secret").generate_key("active_record/signed_id"), digest: "SHA256", serializer: JSON, url_safe: true)
        .generate(1, purpose: "account")
      assert_nil signed_id_verifier.verified(signed_account_id_one_with_legacy_options, purpose: "account")

Review comment (security):
```suggestion
      secret = app.key_generator.generate_key("active_record/signed_id")
      legacy_verifier = ActiveSupport::MessageVerifier.new(secret, digest: "SHA256", serializer: JSON, url_safe: true)

      assert_equal "message", signed_id_verifier.verify(legacy_verifier.generate("message"))
      assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
        legacy_verifier.verify(signed_id_verifier.generate("message"))
      end
```

Code after:

      app "development"

      signed_id_verifier = Rails.application.message_verifiers["active_record/signed_id"]

      secret = app.key_generator.generate_key("active_record/signed_id")
      legacy_verifier = ActiveSupport::MessageVerifier.new(secret, digest: "SHA256", serializer: JSON, url_safe: true)

      assert_equal "message", signed_id_verifier.verify(legacy_verifier.generate("message"))
      assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
        legacy_verifier.verify(signed_id_verifier.generate("message"))
      end
    end

    test "Rails.application.message_verifiers['active_record/signed_id'] does not use legacy options when config.active_record.use_legacy_signed_id_verifier is false" do
      add_to_config <<-RUBY
        config.active_record.use_legacy_signed_id_verifier = false
        config.secret_key_base = "secret"
      RUBY

      app "development"

      signed_id_verifier = Rails.application.message_verifiers["active_record/signed_id"]

      secret = app.key_generator.generate_key("active_record/signed_id")
      legacy_verifier = ActiveSupport::MessageVerifier.new(secret, digest: "SHA256", serializer: JSON, url_safe: true)

      assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
        signed_id_verifier.verify(legacy_verifier.generate("message"))
      end
      assert_raises ActiveSupport::MessageVerifier::InvalidSignature do
        legacy_verifier.verify(signed_id_verifier.generate("message"))
      end
    end

    test "raises when config.active_record.use_legacy_signed_id_verifier has invalid value" do
      add_to_config <<-RUBY
        config.active_record.use_legacy_signed_id_verifier = :invalid_option
      RUBY

      assert_raise(match: /config.active_record.use_legacy_signed_id_verifier/) do
        app "development"
      end
    end

    test "ActiveRecord.message_verifiers is Rails.application.message_verifiers" do
      app "development"

      assert_same Rails.application.message_verifiers, ActiveRecord.message_verifiers
    end