diff --git a/go.mod b/go.mod
index bd6473b4ab7c5d25655421e72e704252c36e33d6..59744c4fea72ec86e9a09122d263cd3d1fa57a30 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,7 @@ require (
 	git.autistici.org/ai3/go-common v0.0.0-20230816213645-b3aa3fb514d6
 	git.autistici.org/id/usermetadb v0.0.0-20230817075814-ec109f54aa90
 	github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746
-	github.com/cenkalti/backoff/v4 v4.1.3
+	github.com/cenkalti/backoff/v4 v4.3.0
 	github.com/coreos/go-systemd/v22 v22.5.0
 	github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499
 	github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
diff --git a/go.sum b/go.sum
index b4e2fdc02fe9074db27e33c92691d5890208b3d9..41d6bed2937b16c7d9563de556720a84c5965e0c 100644
--- a/go.sum
+++ b/go.sum
@@ -173,6 +173,8 @@ github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEe
 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
 github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk=
diff --git a/vendor/github.com/cenkalti/backoff/v4/.travis.yml b/vendor/github.com/cenkalti/backoff/v4/.travis.yml
deleted file mode 100644
index c79105c2fbebe29ea2a4d735de58526f58a06815..0000000000000000000000000000000000000000
--- a/vendor/github.com/cenkalti/backoff/v4/.travis.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-language: go
-go:
-  - 1.13
-  - 1.x
-  - tip
-before_install:
-  - go get github.com/mattn/goveralls
-  - go get golang.org/x/tools/cmd/cover
-script:
-  - $HOME/gopath/bin/goveralls -service=travis-ci
diff --git a/vendor/github.com/cenkalti/backoff/v4/README.md b/vendor/github.com/cenkalti/backoff/v4/README.md
index 16abdfc084f73cb6658c2ddf463ac02ff666dd6e..9433004a28096fd0303a62646caff1747e666b4c 100644
--- a/vendor/github.com/cenkalti/backoff/v4/README.md
+++ b/vendor/github.com/cenkalti/backoff/v4/README.md
@@ -1,4 +1,4 @@
-# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
+# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls]
 
 This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
 
@@ -21,8 +21,6 @@ Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
 
 [godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
 [godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
-[travis]: https://travis-ci.org/cenkalti/backoff
-[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
 [coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
 [coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
 
diff --git a/vendor/github.com/cenkalti/backoff/v4/exponential.go b/vendor/github.com/cenkalti/backoff/v4/exponential.go
index 2c56c1e7189ba605ae668e752b3781f815b1bbd1..aac99f196ad5812349f972dd50b984f4cf7f4cb2 100644
--- a/vendor/github.com/cenkalti/backoff/v4/exponential.go
+++ b/vendor/github.com/cenkalti/backoff/v4/exponential.go
@@ -71,6 +71,9 @@ type Clock interface {
 	Now() time.Time
 }
 
+// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options.
+type ExponentialBackOffOpts func(*ExponentialBackOff)
+
 // Default values for ExponentialBackOff.
 const (
 	DefaultInitialInterval     = 500 * time.Millisecond
@@ -81,7 +84,7 @@ const (
 )
 
 // NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
-func NewExponentialBackOff() *ExponentialBackOff {
+func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff {
 	b := &ExponentialBackOff{
 		InitialInterval:     DefaultInitialInterval,
 		RandomizationFactor: DefaultRandomizationFactor,
@@ -91,10 +94,62 @@ func NewExponentialBackOff() *ExponentialBackOff {
 		Stop:                Stop,
 		Clock:               SystemClock,
 	}
+	for _, fn := range opts {
+		fn(b)
+	}
 	b.Reset()
 	return b
 }
 
+// WithInitialInterval sets the initial interval between retries.
+func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.InitialInterval = duration
+	}
+}
+
+// WithRandomizationFactor sets the randomization factor to add jitter to intervals.
+func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.RandomizationFactor = randomizationFactor
+	}
+}
+
+// WithMultiplier sets the multiplier for increasing the interval after each retry.
+func WithMultiplier(multiplier float64) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.Multiplier = multiplier
+	}
+}
+
+// WithMaxInterval sets the maximum interval between retries.
+func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.MaxInterval = duration
+	}
+}
+
+// WithMaxElapsedTime sets the maximum total time for retries.
+func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.MaxElapsedTime = duration
+	}
+}
+
+// WithRetryStopDuration sets the duration after which retries should stop.
+func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.Stop = duration
+	}
+}
+
+// WithClockProvider sets the clock used to measure time.
+func WithClockProvider(clock Clock) ExponentialBackOffOpts {
+	return func(ebo *ExponentialBackOff) {
+		ebo.Clock = clock
+	}
+}
+
 type systemClock struct{}
 
 func (t systemClock) Now() time.Time {
diff --git a/vendor/github.com/cenkalti/backoff/v4/go.mod b/vendor/github.com/cenkalti/backoff/v4/go.mod
index f811bead99fd33a45a84cbf12c800ade0a4fc832..f41281c3e2cf7a8ced3b536aff07254cf5b45d6b 100644
--- a/vendor/github.com/cenkalti/backoff/v4/go.mod
+++ b/vendor/github.com/cenkalti/backoff/v4/go.mod
@@ -1,3 +1,3 @@
 module github.com/cenkalti/backoff/v4
 
-go 1.13
+go 1.18
diff --git a/vendor/github.com/cenkalti/backoff/v4/retry.go b/vendor/github.com/cenkalti/backoff/v4/retry.go
index 1ce2507ebc8be550a89b07d84e58f0fc55a50ee6..b9c0c51cd755f543a9596384e5b8668651204f5c 100644
--- a/vendor/github.com/cenkalti/backoff/v4/retry.go
+++ b/vendor/github.com/cenkalti/backoff/v4/retry.go
@@ -5,10 +5,20 @@ import (
 	"time"
 )
 
+// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData().
+// The operation will be retried using a backoff policy if it returns an error.
+type OperationWithData[T any] func() (T, error)
+
 // An Operation is executing by Retry() or RetryNotify().
 // The operation will be retried using a backoff policy if it returns an error.
 type Operation func() error
 
+func (o Operation) withEmptyData() OperationWithData[struct{}] {
+	return func() (struct{}, error) {
+		return struct{}{}, o()
+	}
+}
+
 // Notify is a notify-on-error function. It receives an operation error and
 // backoff delay if the operation failed (with an error).
 //
@@ -28,18 +38,41 @@ func Retry(o Operation, b BackOff) error {
 	return RetryNotify(o, b, nil)
 }
 
+// RetryWithData is like Retry but returns data in the response too.
+func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) {
+	return RetryNotifyWithData(o, b, nil)
+}
+
 // RetryNotify calls notify function with the error and wait duration
 // for each failed attempt before sleep.
 func RetryNotify(operation Operation, b BackOff, notify Notify) error {
 	return RetryNotifyWithTimer(operation, b, notify, nil)
 }
 
+// RetryNotifyWithData is like RetryNotify but returns data in the response too.
+func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) {
+	return doRetryNotify(operation, b, notify, nil)
+}
+
 // RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
 // for each failed attempt before sleep.
 // A default timer that uses system timer is used when nil is passed.
 func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
-	var err error
-	var next time.Duration
+	_, err := doRetryNotify(operation.withEmptyData(), b, notify, t)
+	return err
+}
+
+// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too.
+func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
+	return doRetryNotify(operation, b, notify, t)
+}
+
+func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
+	var (
+		err  error
+		next time.Duration
+		res  T
+	)
 	if t == nil {
 		t = &defaultTimer{}
 	}
@@ -52,21 +85,22 @@ func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer
 
 	b.Reset()
 	for {
-		if err = operation(); err == nil {
-			return nil
+		res, err = operation()
+		if err == nil {
+			return res, nil
 		}
 
 		var permanent *PermanentError
 		if errors.As(err, &permanent) {
-			return permanent.Err
+			return res, permanent.Err
 		}
 
 		if next = b.NextBackOff(); next == Stop {
 			if cerr := ctx.Err(); cerr != nil {
-				return cerr
+				return res, cerr
 			}
 
-			return err
+			return res, err
 		}
 
 		if notify != nil {
@@ -77,7 +111,7 @@ func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer
 
 		select {
 		case <-ctx.Done():
-			return ctx.Err()
+			return res, ctx.Err()
 		case <-t.C():
 		}
 	}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index d0e70538fe1094ff19f816dd0e9bf59d3671e03a..71d29c41b78092c31dc9eb556115aeeca50f9edf 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -31,7 +31,7 @@ github.com/boombuler/barcode/utils
 # github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746
 ## explicit
 github.com/bradfitz/gomemcache/memcache
-# github.com/cenkalti/backoff/v4 v4.1.3
+# github.com/cenkalti/backoff/v4 v4.3.0
 ## explicit
 github.com/cenkalti/backoff/v4
 # github.com/census-instrumentation/opencensus-proto v0.3.0