diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 2081a979ab5d582047e4242b97aeb2c50e94de40..9b53828f9ecf8ece649cc9a8710847e5387eea42 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -163,20 +163,38 @@ GET /projects/:id/packages/generic/:package_name/:package_version/:file_name
 
 The file context is served in the response body. The response content type is `application/octet-stream`.
 
+::Tabs
+
+:::TabTitle Personal access token
+
 Example request that uses a personal access token:
 
 ```shell
+# Header authentication
 curl --header "PRIVATE-TOKEN: <your_access_token>" \
      "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
+
+# Basic authentication
+curl --user "user:<your_access_token>" \
+     "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
 ```
 
-Example request that uses HTTP Basic authentication:
+:::TabTitle CI_JOB_TOKEN
+
+Example request that uses a `CI_JOB_TOKEN`:
 
 ```shell
-curl --user "user:<your_access_token>" \
+# Header authentication
+curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
+     "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
+
+# Basic authentication
+curl --user "gitlab-ci-token:${CI_JOB_TOKEN}" \
      "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
 ```
 
+::EndTabs
+
 ## Publish a generic package by using CI/CD
 
 To work with generic packages in [GitLab CI/CD](../../../ci/index.md), you can use
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index 8d1e9e55f24ed2ea7148c3aae2ae3757c1efd591..561883922882a68b5df16fda81cd1e2b5e7d0960 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -119,7 +119,7 @@ class GenericPackages < ::API::Base
             requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.generic_package_file_name_regex, file_path: true
           end
 
-          route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
+          route_setting :authentication, job_token_allowed: %i[request basic_auth], basic_auth_personal_access_token: true, deploy_token_allowed: true
 
           get do
             project = authorized_user_project(action: :read_package)
diff --git a/lib/api/helpers/packages/maven/basic_auth_helpers.rb b/lib/api/helpers/packages/maven/basic_auth_helpers.rb
index c9ef95adc33b20a6811120e4504c02e0a22de5f5..0b0082dc7af9265a86084a718beec93ad3230af3 100644
--- a/lib/api/helpers/packages/maven/basic_auth_helpers.rb
+++ b/lib/api/helpers/packages/maven/basic_auth_helpers.rb
@@ -12,7 +12,7 @@ module BasicAuthHelpers
           # basic auth.
           override :find_user_from_job_token
           def find_user_from_job_token
-            super || find_user_from_basic_auth_job
+            super || find_user_from_job_token_basic_auth
           end
         end
       end
diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb
index 319d1121ec8f04a3e82bcd64680f71f20525f46d..f753db5076b70e39722788329811f1932d644e2e 100644
--- a/lib/gitlab/auth/auth_finders.rb
+++ b/lib/gitlab/auth/auth_finders.rb
@@ -76,30 +76,11 @@ def find_user_from_bearer_token
 
       def find_user_from_job_token
         return unless route_authentication_setting[:job_token_allowed]
-        return find_user_from_basic_auth_job if route_authentication_setting[:job_token_allowed] == :basic_auth
 
-        token = current_request.params[JOB_TOKEN_PARAM].presence ||
-          current_request.params[RUNNER_JOB_TOKEN_PARAM].presence ||
-          current_request.env[JOB_TOKEN_HEADER].presence
-        return unless token
-
-        job = find_valid_running_job_by_token!(token.to_s)
-        @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
-
-        job.user
-      end
-
-      def find_user_from_basic_auth_job
-        return unless has_basic_credentials?(current_request)
+        user = find_user_from_job_token_basic_auth if can_authenticate_job_token_basic_auth?
+        return user if user
 
-        login, password = user_name_and_password(current_request)
-        return unless login.present? && password.present?
-        return unless ::Gitlab::Auth::CI_JOB_USER == login
-
-        job = find_valid_running_job_by_token!(password.to_s)
-        @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
-
-        job.user
+        find_user_from_job_token_query_params_or_header if can_authenticate_job_token_request?
       end
 
       def find_user_from_basic_auth_password
@@ -322,6 +303,41 @@ def find_user_from_path_feed_token(token)
         user
       end
 
+      def can_authenticate_job_token_basic_auth?
+        setting = route_authentication_setting[:job_token_allowed]
+        Array.wrap(setting).include?(:basic_auth)
+      end
+
+      def can_authenticate_job_token_request?
+        setting = route_authentication_setting[:job_token_allowed]
+        setting == true || Array.wrap(setting).include?(:request)
+      end
+
+      def find_user_from_job_token_query_params_or_header
+        token = current_request.params[JOB_TOKEN_PARAM].presence ||
+          current_request.params[RUNNER_JOB_TOKEN_PARAM].presence ||
+          current_request.env[JOB_TOKEN_HEADER].presence
+        return unless token
+
+        job = find_valid_running_job_by_token!(token.to_s)
+        @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
+
+        job.user
+      end
+
+      def find_user_from_job_token_basic_auth
+        return unless has_basic_credentials?(current_request)
+
+        login, password = user_name_and_password(current_request)
+        return unless login.present? && password.present?
+        return unless ::Gitlab::Auth::CI_JOB_USER == login
+
+        job = find_valid_running_job_by_token!(password.to_s)
+        @current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
+
+        job.user
+      end
+
       def parsed_oauth_token
         Doorkeeper::OAuth::Token.from_request(current_request, *Doorkeeper.configuration.access_token_methods)
       end
diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb
index c33ae1ce9013d736cfeb44e5b0ae8331a9a8e149..da13d8e382f9aa49a39fd973783b480d5dedca1e 100644
--- a/lib/gitlab/auth/request_authenticator.rb
+++ b/lib/gitlab/auth/request_authenticator.rb
@@ -38,7 +38,7 @@ def find_sessionless_user(request_format)
           find_user_from_web_access_token(request_format, scopes: [:api, :read_api]) ||
           find_user_from_feed_token(request_format) ||
           find_user_from_static_object_token(request_format) ||
-          find_user_from_basic_auth_job ||
+          find_user_from_job_token_basic_auth ||
           find_user_from_job_token ||
           find_user_from_personal_access_token_for_api_or_git ||
           find_user_for_git_or_lfs_request
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index 26e6cd3661585b9b708d1427f905b874ae0f3618..914d675452c1499302ec5b2b9d1af508c8454946 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -786,8 +786,8 @@ def auth_header_with(token)
     end
   end
 
-  describe '#find_user_from_basic_auth_job' do
-    subject { find_user_from_basic_auth_job }
+  describe '#find_user_from_job_token_basic_auth' do
+    subject { find_user_from_job_token_basic_auth }
 
     context 'when the request does not have AUTHORIZATION header' do
       it { is_expected.to be_nil }
@@ -1037,6 +1037,60 @@ def auth_header_with(token)
       end
     end
 
+    context 'for route_authentication_setting[job_token_allowed]' do
+      using RSpec::Parameterized::TableSyntax
+
+      where(:route_setting, :expect_user_via_request, :expect_user_via_basic_auth) do
+        true                    | true  | false
+        :request                | true  | false
+        [:request]              | true  | false
+        :basic_auth             | false | true
+        [:basic_auth]           | false | true
+        [:request, :basic_auth] | true  | true
+
+        # unexpected values
+        :foo                    | false | false
+        [:foo]                  | false | false
+        [:foo, :bar]            | false | false
+      end
+
+      with_them do
+        let(:route_authentication_setting) { { job_token_allowed: route_setting } }
+
+        context 'when the token is in the headers' do
+          before do
+            set_header(described_class::JOB_TOKEN_HEADER, token)
+          end
+
+          it { is_expected.to eq(expect_user_via_request ? user : nil) }
+        end
+
+        context 'when the token is in the job_token param' do
+          before do
+            set_param(described_class::JOB_TOKEN_PARAM, token)
+          end
+
+          it { is_expected.to eq(expect_user_via_request ? user : nil) }
+        end
+
+        context 'when the token is in the token param' do
+          before do
+            set_param(described_class::RUNNER_JOB_TOKEN_PARAM, token)
+          end
+
+          it { is_expected.to eq(expect_user_via_request ? user : nil) }
+        end
+
+        context 'when the token is in basic auth header' do
+          before do
+            set_basic_auth_header(::Gitlab::Auth::CI_JOB_USER, token)
+          end
+
+          it { is_expected.to eq(expect_user_via_basic_auth ? user : nil) }
+        end
+      end
+    end
+
     context 'when route setting allows job_token' do
       let(:route_authentication_setting) { { job_token_allowed: true } }
 
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index cf9912ba906b98d63d8022f698737d9f707ce0ce..eadd0817fb65810d3a7dd978afee749aad873500 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -29,6 +29,8 @@ def auth_header
       personal_access_token_header
     when :job_token
       job_token_header
+    when :job_basic_auth
+      job_basic_auth_header
     when :invalid_personal_access_token
       personal_access_token_header('wrong token')
     when :invalid_job_token
@@ -61,6 +63,10 @@ def job_token_header(value = nil)
     { Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER => value || ci_build.token }
   end
 
+  def job_basic_auth_header(value = nil)
+    basic_auth_header(Gitlab::Auth::CI_JOB_USER, value || ci_build.token)
+  end
+
   def deploy_token_header(value)
     { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => value }
   end
@@ -564,12 +570,16 @@ def upload_file(params, request_headers, send_rewritten_field: true, package_nam
         'PRIVATE' | :guest     | false | :invalid_user_basic_auth       | :unauthorized
         'PRIVATE' | :anonymous | false | :none                          | :unauthorized
         'PUBLIC'  | :developer | true  | :job_token                     | :success
+        'PUBLIC'  | :developer | true  | :job_basic_auth                | :success
         'PUBLIC'  | :developer | true  | :invalid_job_token             | :unauthorized
         'PUBLIC'  | :developer | false | :job_token                     | :success
+        'PUBLIC'  | :developer | false | :job_basic_auth                | :success
         'PUBLIC'  | :developer | false | :invalid_job_token             | :unauthorized
         'PRIVATE' | :developer | true  | :job_token                     | :success
+        'PRIVATE' | :developer | true  | :job_basic_auth                | :success
         'PRIVATE' | :developer | true  | :invalid_job_token             | :unauthorized
         'PRIVATE' | :developer | false | :job_token                     | :not_found
+        'PRIVATE' | :developer | false | :job_basic_auth                | :not_found
         'PRIVATE' | :developer | false | :invalid_job_token             | :unauthorized
       end