# frozen_string_literal: true require "test_helper" class DsnAuthenticationServiceTest < ActiveSupport::TestCase def setup @dsn = Dsn.create!(name: "Test DSN", key: "test-auth-key-1234567890abcdef") end test "should authenticate via query parameter baffle_key" do request = ActionDispatch::TestRequest.create request.query_parameters = { "baffle_key" => @dsn.key } authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should authenticate via query parameter sentry_key" do request = ActionDispatch::TestRequest.create request.query_parameters = { "sentry_key" => @dsn.key } authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should authenticate via query parameter glitchtip_key" do request = ActionDispatch::TestRequest.create request.query_parameters = { "glitchtip_key" => @dsn.key } authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should authenticate via X-Baffle-Auth header" do request = ActionDispatch::TestRequest.create request.headers["X-Baffle-Auth"] = "Baffle baffle_key=#{@dsn.key}, baffle_version=1" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should authenticate via X-Sentry-Auth header" do request = ActionDispatch::TestRequest.create request.headers["X-Sentry-Auth"] = "Sentry sentry_key=#{@dsn.key}, sentry_version=7" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should authenticate via Authorization Bearer header" do request = ActionDispatch::TestRequest.create request.headers["Authorization"] = "Bearer #{@dsn.key}" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should authenticate via Basic auth with username as key" do request = ActionDispatch::TestRequest.create credentials = Base64.strict_encode64("#{@dsn.key}:ignored-password") request.headers["Authorization"] = "Basic #{credentials}" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should prioritize query parameter over other methods" do request = ActionDispatch::TestRequest.create request.query_parameters = { "baffle_key" => @dsn.key } request.headers["Authorization"] = "Bearer wrong-key" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should fail authentication with disabled DSN" do @dsn.update!(enabled: false) request = ActionDispatch::TestRequest.create request.query_parameters = { "baffle_key" => @dsn.key } assert_raises(DsnAuthenticationService::AuthenticationError) do DsnAuthenticationService.authenticate(request) end end test "should fail authentication with non-existent key" do request = ActionDispatch::TestRequest.create request.query_parameters = { "baffle_key" => "non-existent-key" } assert_raises(DsnAuthenticationService::AuthenticationError) do DsnAuthenticationService.authenticate(request) end end test "should fail authentication with no authentication method" do request = ActionDispatch::TestRequest.create assert_raises(DsnAuthenticationService::AuthenticationError) do DsnAuthenticationService.authenticate(request) end end test "should handle malformed Authorization header" do request = ActionDispatch::TestRequest.create request.headers["Authorization"] = "InvalidHeader" assert_nil DsnAuthenticationService.authenticate(request) end test "should handle malformed Basic auth" do request = ActionDispatch::TestRequest.create request.headers["Authorization"] = "Basic invalid-base64" assert_nil DsnAuthenticationService.authenticate(request) end test "should handle malformed X-Baffle-Auth header" do request = ActionDispatch::TestRequest.create request.headers["X-Baffle-Auth"] = "Invalid format" assert_nil DsnAuthenticationService.authenticate(request) end test "should handle empty query parameters" do request = ActionDispatch::TestRequest.create request.query_parameters = { "baffle_key" => "" } assert_nil DsnAuthenticationService.authenticate(request) end test "should extract key from complex X-Baffle-Auth header" do request = ActionDispatch::TestRequest.create request.headers["X-Baffle-Auth"] = "Baffle baffle_key=#{@dsn.key}, baffle_version=1, baffle_client=ruby-2.0.0" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should handle URL-style DSN in Basic auth" do # This simulates using the full DSN URL: https://key@domain.com request = ActionDispatch::TestRequest.create credentials = Base64.strict_encode64("#{@dsn.key}:") request.headers["Authorization"] = "Basic #{credentials}" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal @dsn, authenticated_dsn end test "should handle special characters in DSN keys" do special_dsn = Dsn.create!(name: "Special DSN", key: "special-key-with-dashes_123") request = ActionDispatch::TestRequest.create request.headers["Authorization"] = "Bearer #{special_dsn.key}" authenticated_dsn = DsnAuthenticationService.authenticate(request) assert_equal special_dsn, authenticated_dsn end end