github.com/thuongh2/go-security-redis, so go-security’s own
go.mod never gains a Redis client — only applications that actually need
Redis pay that dependency cost. That module is not part of this repository;
this page documents the contracts it must satisfy, per
docs/INTEGRATION.md, so you know what to expect from it (or what to
implement yourself against any other backend — Postgres, DynamoDB, etc.).
Installation
Why a separate module
Adding a Redis client togo-security’s go.mod would force every
application using go-security to pull it in, even ones that use Postgres or
an in-memory store. The separate module depends on go-security in one
direction only; import it in your app, not in go-security itself.
Adapter contracts
An adapter is just a Go type implementing one of go-security’s existing store/repository interfaces — there is no Redis-specific type ingo-security itself. Four contracts matter for a distributed deployment:
A non-atomic
IncrAndExpire (read the count, then write count+1 and an
expiry as two separate round trips) is a rate-limit-bypass vulnerability:
an attacker parallelizes requests and each one reads the stale count before
any write lands, letting far more than the configured limit through. Implement
it as a single Lua script or pipeline:
session.Session that session.Store already
persists (see oauth2.LoginConfig.Store). Implementing session.Store over
Redis covers OAuth2 state for free — there is no oauth2.WithStateStore or
similar option to configure separately.
Wiring an adapter in
Forlockout, a Redis-backed Store drops straight into the same
Policy/GuardProvider wiring documented in lockout —
nothing else changes:
ratelimit is different: NewTokenBucketLimiter is in-process only, and
ratelimit.Store has no built-in bridge to ratelimit.Limiter/Middleware in
this repo — nothing here converts a Store into something
securityhttp.WithRateLimit or ratelimit.Middleware can consume. An
adapter module that wants a distributed rate limiter therefore implements
ratelimit.Limiter itself (Allow/AllowN) with Redis fixed-window logic
inside, using the ratelimit.Store shape (and StoreConformance) to prove
that inner logic is correct — it is a correctness contract for the adapter’s
internals, not a plug-in point wired up elsewhere in go-security.
Proving an adapter: the conformance harness
Bothratelimit and lockout export a test harness so an adapter proves
parity with the in-memory reference — atomic increment (no lost updates under
concurrency), window/lock TTL honored, and reset — in the adapter module’s own
CI:
ratelimit.MemoryStore and lockout.MemoryStore pass these same
harnesses — they are the executable definition of each contract, not just
prose.
