feat: 实现 OIDC 服务端会话与请求刷新
使用 AES-256-GCM 保存认证中心令牌,并以随机 Cookie 哈希关联 PostgreSQL 会话。加入闲置与绝对期限、Refresh Token 轮换以及多实例刷新锁。
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package oidcsession
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLoginTransactionIsEncryptedBoundedAndPKCES256(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)
|
||||
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")
|
||||
}
|
||||
encoded, err := cipher.EncodeLoginTransaction(transaction)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.Contains(encoded, transaction.State) || strings.Contains(encoded, transaction.PKCEVerifier) {
|
||||
t.Fatal("login transaction cookie contains plaintext security material")
|
||||
}
|
||||
decoded, err := cipher.DecodeLoginTransaction(encoded, now.Add(9*time.Minute))
|
||||
if err != nil || decoded.ReturnTo != transaction.ReturnTo {
|
||||
t.Fatalf("decode transaction=%#v err=%v", decoded, err)
|
||||
}
|
||||
if _, err := cipher.DecodeLoginTransaction(encoded, now.Add(10*time.Minute)); err == nil {
|
||||
t.Fatal("10-minute login transaction was accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidReturnToRejectsOpenRedirects(t *testing.T) {
|
||||
for _, value := range []string{"https://evil.example", "//evil.example", "/\\evil", "", "workspace"} {
|
||||
if ValidReturnTo(value) {
|
||||
t.Fatalf("unsafe returnTo accepted: %q", value)
|
||||
}
|
||||
}
|
||||
if !ValidReturnTo("/workspace/tasks?from=login#latest") {
|
||||
t.Fatal("safe relative returnTo was rejected")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user