This is an automated email from the ASF dual-hosted git repository.

klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new c44091702 fix(github): backdate GitHub App JWT iat to tolerate clock 
drift (#9230)
c44091702 is described below

commit c44091702ac464f07ce77ba06a1c676f00030c76
Author: Rasmus Rask <[email protected]>
AuthorDate: Sun Oct 18 08:12:09 2026 +0200

    fix(github): backdate GitHub App JWT iat to tolerate clock drift (#9230)
---
 backend/plugins/github/models/connection.go      |  5 +++--
 backend/plugins/github/models/connection_test.go | 28 ++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/backend/plugins/github/models/connection.go 
b/backend/plugins/github/models/connection.go
index f0cac2d47..9ec6eecc3 100644
--- a/backend/plugins/github/models/connection.go
+++ b/backend/plugins/github/models/connection.go
@@ -391,9 +391,10 @@ func (gak *GithubAppKey) CreateJwt() (string, 
errors.Error) {
        token := jwt.New(jwt.SigningMethodRS256)
        t := time.Now().Unix()
 
+       // Backdate iat and keep exp under GitHub's 10 minute limit to tolerate 
clock drift
        token.Claims = jwt.MapClaims{
-               "iat": t,
-               "exp": t + (10 * 60),
+               "iat": t - 60,
+               "exp": t + (9 * 60),
                "iss": gak.AppId,
        }
 
diff --git a/backend/plugins/github/models/connection_test.go 
b/backend/plugins/github/models/connection_test.go
index feddab69e..55e55075f 100644
--- a/backend/plugins/github/models/connection_test.go
+++ b/backend/plugins/github/models/connection_test.go
@@ -18,11 +18,17 @@ limitations under the License.
 package models
 
 import (
+       "crypto/rand"
+       "crypto/rsa"
+       "crypto/x509"
+       "encoding/pem"
        "github.com/apache/devlake/core/models/common"
        "github.com/apache/devlake/helpers/pluginhelper/api"
        "testing"
+       "time"
 
        "github.com/go-playground/validator/v10"
+       "github.com/golang-jwt/jwt/v5"
        "github.com/stretchr/testify/assert"
 )
 
@@ -280,3 +286,25 @@ func TestGithubConnection_GetHash(t *testing.T) {
                })
        }
 }
+
+func TestGithubAppKey_CreateJwtToleratesClockDrift(t *testing.T) {
+       key, err := rsa.GenerateKey(rand.Reader, 2048)
+       assert.NoError(t, err)
+       appKey := &GithubAppKey{}
+       appKey.AppId = "123"
+       appKey.SecretKey = string(pem.EncodeToMemory(&pem.Block{Type: "RSA 
PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}))
+
+       before := time.Now().Unix()
+       tokenString, jwtErr := appKey.CreateJwt()
+       after := time.Now().Unix()
+       assert.Nil(t, jwtErr)
+
+       claims := jwt.MapClaims{}
+       _, err = jwt.ParseWithClaims(tokenString, claims, func(*jwt.Token) 
(any, error) { return &key.PublicKey, nil })
+       assert.NoError(t, err)
+       iat, _ := claims.GetIssuedAt()
+       exp, _ := claims.GetExpirationTime()
+       assert.LessOrEqual(t, iat.Unix(), after-60)
+       assert.GreaterOrEqual(t, iat.Unix(), before-60)
+       assert.LessOrEqual(t, exp.Unix(), after+540)
+}

Reply via email to