fix: tolerate retried internal api nonce
This commit is contained in:
+22
-8
@@ -185,7 +185,8 @@ func authorizeInternalAPI(wrt http.ResponseWriter, req *http.Request, capability
|
||||
writeIMError(wrt, req, http.StatusUnauthorized, 30043, imReasonAuthRequired, "invalid internal signature", nil)
|
||||
return false
|
||||
}
|
||||
if !claimInternalNonce(serviceName, nonce, time.Now().Add(window)) {
|
||||
requestClaim := internalRequestClaimValue(signingText)
|
||||
if !claimInternalNonce(serviceName, nonce, requestClaim, time.Now().Add(window)) {
|
||||
writeIMError(wrt, req, http.StatusUnauthorized, 30043, imReasonAuthRequired, "internal nonce replayed", nil)
|
||||
return false
|
||||
}
|
||||
@@ -572,23 +573,36 @@ func verifyInternalSignature(secret, signingText, signature string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func claimInternalNonce(serviceName, nonce string, expiresAt time.Time) bool {
|
||||
func claimInternalNonce(serviceName, nonce, requestClaim string, expiresAt time.Time) bool {
|
||||
ttl := time.Until(expiresAt)
|
||||
if ok, enabled, err := store.ClaimShortState("internal_api_nonce", fmt.Sprintf("%s:%s", serviceName, nonce), ttl); enabled {
|
||||
nonceKey := fmt.Sprintf("%s:%s", serviceName, nonce)
|
||||
if claimed, sameValue, enabled, err := store.ClaimShortStateValue("internal_api_nonce", nonceKey, requestClaim, ttl); enabled {
|
||||
if err != nil {
|
||||
logs.Warn.Println("internal api: failed to claim nonce in redis", err)
|
||||
return false
|
||||
}
|
||||
return ok
|
||||
return claimed || sameValue
|
||||
}
|
||||
now := time.Now()
|
||||
internalAPI.nonces.Range(func(key, value any) bool {
|
||||
if expires, ok := value.(time.Time); ok && expires.Before(now) {
|
||||
if claim, ok := value.(internalNonceClaim); ok && claim.expiresAt.Before(now) {
|
||||
internalAPI.nonces.Delete(key)
|
||||
}
|
||||
return true
|
||||
})
|
||||
nonceKey := fmt.Sprintf("%s:%s", serviceName, nonce)
|
||||
_, loaded := internalAPI.nonces.LoadOrStore(nonceKey, expiresAt)
|
||||
return !loaded
|
||||
if existing, loaded := internalAPI.nonces.LoadOrStore(nonceKey, internalNonceClaim{value: requestClaim, expiresAt: expiresAt}); loaded {
|
||||
claim, ok := existing.(internalNonceClaim)
|
||||
return ok && claim.value == requestClaim
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type internalNonceClaim struct {
|
||||
value string
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func internalRequestClaimValue(signingText string) string {
|
||||
sum := sha256.Sum256([]byte(signingText))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user