A community based topic aggregation platform built on atproto

refactor(auth): optimize Claims struct and fix linting issues

JWT improvements:
- Add Confirmation field for DPoP cnf.jkt claim binding
- Reorder Claims struct fields for optimal memory alignment

Test improvements:
- Replace os.Setenv/os.Unsetenv with t.Setenv for cleaner tests
- Use t.Cleanup for automatic environment restoration
- Use UUID for DPoP proof jti to ensure test uniqueness

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Changed files
+36 -74
internal
atproto
+4 -1
internal/atproto/auth/jwt.go
···
// Claims represents the standard JWT claims we care about
type Claims struct {
jwt.RegisteredClaims
-
Scope string `json:"scope,omitempty"`
+
// Confirmation claim for DPoP token binding (RFC 9449)
+
// Contains "jkt" (JWK thumbprint) when token is bound to a DPoP key
+
Confirmation map[string]interface{} `json:"cnf,omitempty"`
+
Scope string `json:"scope,omitempty"`
}
// stripBearerPrefix removes the "Bearer " prefix from a token string
+32 -73
internal/atproto/auth/jwt_test.go
···
import (
"context"
-
"os"
"testing"
"time"
···
issuer := "https://pds.coves.social"
ResetJWTConfigForTesting()
-
os.Setenv("PDS_JWT_SECRET", secret)
-
os.Setenv("HS256_ISSUERS", issuer)
-
defer func() {
-
os.Unsetenv("PDS_JWT_SECRET")
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("PDS_JWT_SECRET", secret)
+
t.Setenv("HS256_ISSUERS", issuer)
+
t.Cleanup(ResetJWTConfigForTesting)
tokenString := createHS256Token(t, "did:plc:test123", issuer, secret, 1*time.Hour)
···
issuer := "https://pds.coves.social"
ResetJWTConfigForTesting()
-
os.Setenv("PDS_JWT_SECRET", "correct-secret")
-
os.Setenv("HS256_ISSUERS", issuer)
-
defer func() {
-
os.Unsetenv("PDS_JWT_SECRET")
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("PDS_JWT_SECRET", "correct-secret")
+
t.Setenv("HS256_ISSUERS", issuer)
+
t.Cleanup(ResetJWTConfigForTesting)
// Create token with wrong secret
tokenString := createHS256Token(t, "did:plc:test123", issuer, "wrong-secret", 1*time.Hour)
···
issuer := "https://pds.coves.social"
ResetJWTConfigForTesting()
-
os.Unsetenv("PDS_JWT_SECRET") // Ensure secret is not set
-
os.Setenv("HS256_ISSUERS", issuer)
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("PDS_JWT_SECRET", "") // Ensure secret is not set (empty = not configured)
+
t.Setenv("HS256_ISSUERS", issuer)
+
t.Cleanup(ResetJWTConfigForTesting)
tokenString := createHS256Token(t, "did:plc:test123", issuer, "any-secret", 1*time.Hour)
···
// An attacker tries to use HS256 with an issuer that should use RS256/ES256
ResetJWTConfigForTesting()
-
os.Setenv("PDS_JWT_SECRET", "some-secret")
-
os.Setenv("HS256_ISSUERS", "https://trusted.example.com") // Different from token issuer
-
defer func() {
-
os.Unsetenv("PDS_JWT_SECRET")
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("PDS_JWT_SECRET", "some-secret")
+
t.Setenv("HS256_ISSUERS", "https://trusted.example.com") // Different from token issuer
+
t.Cleanup(ResetJWTConfigForTesting)
// Create HS256 token with non-whitelisted issuer (simulating attack)
tokenString := createHS256Token(t, "did:plc:attacker", "https://victim-pds.example.com", "some-secret", 1*time.Hour)
···
// SECURITY TEST: When no issuers are whitelisted for HS256, all HS256 tokens should be rejected
ResetJWTConfigForTesting()
-
os.Setenv("PDS_JWT_SECRET", "some-secret")
-
os.Unsetenv("HS256_ISSUERS") // Empty whitelist
-
defer func() {
-
os.Unsetenv("PDS_JWT_SECRET")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("PDS_JWT_SECRET", "some-secret")
+
t.Setenv("HS256_ISSUERS", "") // Empty whitelist
+
t.Cleanup(ResetJWTConfigForTesting)
tokenString := createHS256Token(t, "did:plc:test123", "https://any-pds.example.com", "some-secret", 1*time.Hour)
···
issuer := "https://pds.coves.social"
ResetJWTConfigForTesting()
-
os.Setenv("PDS_JWT_SECRET", "test-secret")
-
os.Setenv("HS256_ISSUERS", issuer)
-
defer func() {
-
os.Unsetenv("PDS_JWT_SECRET")
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("PDS_JWT_SECRET", "test-secret")
+
t.Setenv("HS256_ISSUERS", issuer)
+
t.Cleanup(ResetJWTConfigForTesting)
// Create RS256-signed token (can't actually sign without RSA key, but we can test the header check)
claims := &Claims{
···
func TestIsHS256IssuerWhitelisted_Whitelisted(t *testing.T) {
ResetJWTConfigForTesting()
-
os.Setenv("HS256_ISSUERS", "https://pds1.example.com,https://pds2.example.com")
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("HS256_ISSUERS", "https://pds1.example.com,https://pds2.example.com")
+
t.Cleanup(ResetJWTConfigForTesting)
if !isHS256IssuerWhitelisted("https://pds1.example.com") {
t.Error("Expected pds1 to be whitelisted")
···
func TestIsHS256IssuerWhitelisted_NotWhitelisted(t *testing.T) {
ResetJWTConfigForTesting()
-
os.Setenv("HS256_ISSUERS", "https://pds1.example.com")
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("HS256_ISSUERS", "https://pds1.example.com")
+
t.Cleanup(ResetJWTConfigForTesting)
if isHS256IssuerWhitelisted("https://attacker.example.com") {
t.Error("Expected non-whitelisted issuer to return false")
···
func TestIsHS256IssuerWhitelisted_EmptyWhitelist(t *testing.T) {
ResetJWTConfigForTesting()
-
os.Unsetenv("HS256_ISSUERS")
-
defer ResetJWTConfigForTesting()
+
t.Setenv("HS256_ISSUERS", "") // Empty whitelist
+
t.Cleanup(ResetJWTConfigForTesting)
if isHS256IssuerWhitelisted("https://any.example.com") {
t.Error("Expected false when whitelist is empty (safe default)")
···
func TestIsHS256IssuerWhitelisted_WhitespaceHandling(t *testing.T) {
ResetJWTConfigForTesting()
-
os.Setenv("HS256_ISSUERS", " https://pds1.example.com , https://pds2.example.com ")
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("HS256_ISSUERS", " https://pds1.example.com , https://pds2.example.com ")
+
t.Cleanup(ResetJWTConfigForTesting)
if !isHS256IssuerWhitelisted("https://pds1.example.com") {
t.Error("Expected whitespace-trimmed issuer to be whitelisted")
···
func TestShouldUseHS256_WithKid_AlwaysFalse(t *testing.T) {
// Tokens with kid should NEVER use HS256, regardless of issuer whitelist
ResetJWTConfigForTesting()
-
os.Setenv("HS256_ISSUERS", "https://whitelisted.example.com")
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("HS256_ISSUERS", "https://whitelisted.example.com")
+
t.Cleanup(ResetJWTConfigForTesting)
header := &JWTHeader{
Alg: AlgorithmHS256,
···
func TestShouldUseHS256_WithoutKid_WhitelistedIssuer(t *testing.T) {
ResetJWTConfigForTesting()
-
os.Setenv("HS256_ISSUERS", "https://my-pds.example.com")
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("HS256_ISSUERS", "https://my-pds.example.com")
+
t.Cleanup(ResetJWTConfigForTesting)
header := &JWTHeader{
Alg: AlgorithmHS256,
···
func TestShouldUseHS256_WithoutKid_NotWhitelisted(t *testing.T) {
ResetJWTConfigForTesting()
-
os.Setenv("HS256_ISSUERS", "https://my-pds.example.com")
-
defer func() {
-
os.Unsetenv("HS256_ISSUERS")
-
ResetJWTConfigForTesting()
-
}()
+
t.Setenv("HS256_ISSUERS", "https://my-pds.example.com")
+
t.Cleanup(ResetJWTConfigForTesting)
header := &JWTHeader{
Alg: AlgorithmHS256,