From dd1ddd6eadc506cd72c44ba1f798ae75702febff Mon Sep 17 00:00:00 2001 From: chengcheng Date: Tue, 14 Jul 2026 10:24:19 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=BB=9F=E4=B8=80=20PKCE=20?= =?UTF-8?q?=E6=8C=91=E6=88=98=E5=80=BC=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/internal/httpapi/oidc_session.go | 2 +- apps/api/internal/httpapi/oidc_session_test.go | 2 +- .../api/internal/oidcsession/login_transaction.go | 15 ++++++--------- .../oidcsession/login_transaction_test.go | 8 ++++---- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/api/internal/httpapi/oidc_session.go b/apps/api/internal/httpapi/oidc_session.go index 037cb84..0b21a2d 100644 --- a/apps/api/internal/httpapi/oidc_session.go +++ b/apps/api/internal/httpapi/oidc_session.go @@ -48,7 +48,7 @@ func (s *Server) startOIDCLogin(w http.ResponseWriter, r *http.Request) { if returnTo == "" { returnTo = "/" } - transaction, _, err := oidcsession.NewLoginTransaction(returnTo, time.Now()) + transaction, err := oidcsession.NewLoginTransaction(returnTo, time.Now()) if err != nil { writeError(w, http.StatusBadRequest, "登录后返回地址无效", errorCodeOIDCLoginInvalid) return diff --git a/apps/api/internal/httpapi/oidc_session_test.go b/apps/api/internal/httpapi/oidc_session_test.go index 0e6f351..9c3d442 100644 --- a/apps/api/internal/httpapi/oidc_session_test.go +++ b/apps/api/internal/httpapi/oidc_session_test.go @@ -66,7 +66,7 @@ func TestCompleteOIDCLoginReportsSafeTransactionFailureReason(t *testing.T) { if err != nil { t.Fatal(err) } - transaction, _, err := oidcsession.NewLoginTransaction("/", time.Now()) + transaction, err := oidcsession.NewLoginTransaction("/", time.Now()) if err != nil { t.Fatal(err) } diff --git a/apps/api/internal/oidcsession/login_transaction.go b/apps/api/internal/oidcsession/login_transaction.go index f670263..ac5359f 100644 --- a/apps/api/internal/oidcsession/login_transaction.go +++ b/apps/api/internal/oidcsession/login_transaction.go @@ -2,7 +2,6 @@ package oidcsession import ( "crypto/rand" - "crypto/sha256" "encoding/base64" "errors" "net/url" @@ -22,25 +21,23 @@ type LoginTransaction struct { CreatedAt time.Time `json:"createdAt"` } -func NewLoginTransaction(returnTo string, now time.Time) (LoginTransaction, string, error) { +func NewLoginTransaction(returnTo string, now time.Time) (LoginTransaction, error) { if !ValidReturnTo(returnTo) { - return LoginTransaction{}, "", errors.New("returnTo must be a same-origin relative path") + return LoginTransaction{}, errors.New("returnTo must be a same-origin relative path") } state, err := randomBase64URL(32) if err != nil { - return LoginTransaction{}, "", err + return LoginTransaction{}, err } nonce, err := randomBase64URL(32) if err != nil { - return LoginTransaction{}, "", err + return LoginTransaction{}, err } verifier, err := randomBase64URL(32) if err != nil { - return LoginTransaction{}, "", err + return LoginTransaction{}, err } - challengeHash := sha256.Sum256([]byte(verifier)) - return LoginTransaction{State: state, Nonce: nonce, PKCEVerifier: verifier, ReturnTo: returnTo, CreatedAt: now.UTC()}, - base64.RawURLEncoding.EncodeToString(challengeHash[:]), nil + return LoginTransaction{State: state, Nonce: nonce, PKCEVerifier: verifier, ReturnTo: returnTo, CreatedAt: now.UTC()}, nil } func (c *Cipher) EncodeLoginTransaction(transaction LoginTransaction) (string, error) { diff --git a/apps/api/internal/oidcsession/login_transaction_test.go b/apps/api/internal/oidcsession/login_transaction_test.go index c2bf43b..bdc8d73 100644 --- a/apps/api/internal/oidcsession/login_transaction_test.go +++ b/apps/api/internal/oidcsession/login_transaction_test.go @@ -7,15 +7,15 @@ import ( "time" ) -func TestLoginTransactionIsEncryptedBoundedAndPKCES256(t *testing.T) { +func TestLoginTransactionIsEncryptedAndBounded(t *testing.T) { now := time.Date(2026, 7, 13, 12, 0, 0, 0, time.UTC) cipher, _ := NewCipher(bytes.Repeat([]byte{9}, 32)) - transaction, challenge, err := NewLoginTransaction("/workspace?tab=wallet", now) + transaction, err := NewLoginTransaction("/workspace?tab=wallet", now) if err != nil { t.Fatal(err) } - if transaction.State == transaction.Nonce || len(challenge) != 43 || challenge == transaction.PKCEVerifier { - t.Fatal("state, nonce and PKCE values are not independent S256 material") + if transaction.State == transaction.Nonce || len(transaction.PKCEVerifier) != 43 || transaction.State == transaction.PKCEVerifier { + t.Fatal("state, nonce and PKCE verifier are not independent security material") } encoded, err := cipher.EncodeLoginTransaction(transaction) if err != nil {