使用 AES-256-GCM 保存认证中心令牌,并以随机 Cookie 哈希关联 PostgreSQL 会话。加入闲置与绝对期限、Refresh Token 轮换以及多实例刷新锁。
46 lines
1.5 KiB
Go
46 lines
1.5 KiB
Go
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")
|
|
}
|
|
}
|