From a294195e5b2a9580d0c2c1dc4069cff2856e84bb Mon Sep 17 00:00:00 2001
From: Stan Hu <stanhu@gmail.com>
Date: Mon, 24 Jul 2023 10:08:16 -0700
Subject: [PATCH] Disable IAT verification by default

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117468 in GitLab
15.11 updated the ruby-jwt gem to v2.5.0. In v2.2.0, ruby-jwt removed
the `iat_leeway` parameter (https://github.com/jwt/ruby-jwt/pull/274).

As a result, if a gitlab-shell host creates a JWT token with an
issued-at (IAT) claim that is slightly behind the host handling API
the request, users will receive a 401 error.

Disable this IAT verification by default since it's not serving a
useful purpose, since expiration times are already validated. We
already made a similar change in Geo.

Relates to https://gitlab.com/gitlab-org/gitlab/-/issues/417543

Changelog: fixed
---
 lib/json_web_token/hmac_token.rb           |  4 ++--
 spec/lib/json_web_token/hmac_token_spec.rb |  2 +-
 spec/requests/api/internal/base_spec.rb    | 11 +++++++++++
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/lib/json_web_token/hmac_token.rb b/lib/json_web_token/hmac_token.rb
index ec0917ab49d84f2f..7f69a7550c7cc813 100644
--- a/lib/json_web_token/hmac_token.rb
+++ b/lib/json_web_token/hmac_token.rb
@@ -4,7 +4,7 @@
 
 module JSONWebToken
   class HMACToken < Token
-    IAT_LEEWAY = 60
+    LEEWAY = 60
     JWT_ALGORITHM = 'HS256'
 
     def initialize(secret)
@@ -13,7 +13,7 @@ def initialize(secret)
       @secret = secret
     end
 
-    def self.decode(token, secret, leeway: IAT_LEEWAY, verify_iat: true)
+    def self.decode(token, secret, leeway: LEEWAY, verify_iat: false)
       JWT.decode(token, secret, true, leeway: leeway, verify_iat: verify_iat, algorithm: JWT_ALGORITHM)
     end
 
diff --git a/spec/lib/json_web_token/hmac_token_spec.rb b/spec/lib/json_web_token/hmac_token_spec.rb
index 7c486b2fe1b0fb62..877184a4a3d15e3b 100644
--- a/spec/lib/json_web_token/hmac_token_spec.rb
+++ b/spec/lib/json_web_token/hmac_token_spec.rb
@@ -25,7 +25,7 @@
   end
 
   describe '.decode' do
-    let(:leeway) { described_class::IAT_LEEWAY }
+    let(:leeway) { described_class::LEEWAY }
     let(:decoded_token) { described_class.decode(encoded_token, secret, leeway: leeway) }
 
     context 'with an invalid token' do
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index dff41c4c4773b7b5..2004fd0a0ec92fc7 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -47,6 +47,17 @@ def perform_request(headers: gitlab_shell_internal_api_request_header)
         expect(response).to have_gitlab_http_status(:ok)
       end
 
+      it 'authenticates using a jwt token with an IAT from 10 seconds in the future' do
+        headers =
+          travel_to(Time.now + 10.seconds) do
+            gitlab_shell_internal_api_request_header
+          end
+
+        perform_request(headers: headers)
+
+        expect(response).to have_gitlab_http_status(:ok)
+      end
+
       it 'returns 401 when jwt token is expired' do
         headers = gitlab_shell_internal_api_request_header
 
-- 
GitLab