feat(middleware): add M2M authentication gate#125
Conversation
Add M2MAuthenticator, a Fiber v3 middleware (RequireM2M) that authenticates machine-to-machine callers by verifying a Casdoor-issued RS256 application token offline against an injected RSA public key (the issuer certificate), so any service can reuse it by supplying its own cert. No network round-trip and no Casdoor SDK dependency. It authenticates only: RS256 is pinned (closing none/HS256 alg substitution), expiry is required, and the token type must be "application". It does not authorize and does not bind the caller to a target slug; that ownership check is intentionally out of scope, with possession of a valid, manually-provisioned M2M token as the trust boundary. The authenticated identity (sub, azp) is exposed to downstream handlers via M2MSubjectFromContext / M2MClientIDFromContext. Every failure path fails closed (401/403); when disabled the middleware is a pass-through, and an enabled authenticator requires a parseable cert at construction. X-Lerian-Ref: 0x1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds configurable Fiber middleware for offline Casdoor RS256 M2M token authentication. It validates JWT claims, returns ChangesM2M authentication
Sequence Diagram(s)sequenceDiagram
participant Client
participant RequireM2M
participant verify
participant DownstreamHandler
Client->>RequireM2M: Send request with bearer token
RequireM2M->>verify: Validate JWT
verify-->>RequireM2M: Return verified sub and azp
RequireM2M->>DownstreamHandler: Set Fiber locals and continue
DownstreamHandler-->>Client: Return response with M2M identity
✨ Finishing Touches✨ Simplify code
Comment |
The M2M gate verified the RS256 signature but ignored the "iss" claim, so any application token signed by the same key passed regardless of issuer. This is safe in a single-issuer deployment but becomes cross-issuer token reuse if one signing key ever serves multiple issuers/orgs. NewM2MAuthenticator now takes an expectedIssuer: when non-empty it pins the token issuer via jwt.WithIssuer; empty keeps the prior behavior (no issuer check) for single-issuer/dev setups. Audience is deliberately not pinned here — a Casdoor client_credentials token carries the caller's own clientId as aud, so pinning specific audiences would be the app<->slug ownership binding that is intentionally out of scope (Option B). X-Lerian-Ref: 0x1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 3.0.0-beta.4 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
## [3.0.0](v2.9.0...v3.0.0) (2026-07-22) ### ⚠ BREAKING CHANGES * **middleware:** module path is now github.com/LerianStudio/lib-auth/v3 and the Authorize middleware requires Fiber v3. X-Lerian-Ref: 0x1 ### Features * **middleware:** add authz cache, circuit breaker, and bounded retry ([c0469e6](c0469e6)), closes [#107](#107) [#127](#127) [#127](#127) [#108](#108) * **middleware:** add fail-closed AUTH_REQUIRED option ([f7fff6c](f7fff6c)), closes [#107](#107) * **middleware:** add M2M authentication gate ([2034198](2034198)) * **middleware:** add opt-in local JWT signature verification ([#128](#128)) ([48b81a3](48b81a3)), closes [#106](#106) * **middleware:** add optional issuer pinning to M2M gate ([5afd305](5afd305)) * **middleware:** expose M2M identity via request context ([c48393a](c48393a)), closes [#125](#125) * **middleware:** forward product on M2M auth (flag-gated) ([93c44db](93c44db)) * **middleware:** migrate to Fiber v3, cut /v3 major ([024a909](024a909)) * real M2M subject and token type whitelist ([e31ac53](e31ac53)) ### Bug Fixes * **middleware:** return zero M2MIdentity when reporting absent ([25fc4ec](25fc4ec)), closes [#126](#126)
|
🎉 This PR is included in version 3.0.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
O quê
Adiciona
M2MAuthenticator— um middleware Fiber v3 (RequireM2M) que autentica chamadores machine-to-machine verificando um token de aplicação (M2M) emitido pelo Casdoor.É a fundação do gate do endpoint de declarações (
PUT /v1/declarations/{slug}) da inversão do access-manager: cada plugin passa a declarar suas próprias permissions via manifest, e esse endpoint precisa de uma trava que prove que quem chama é uma aplicação M2M legítima. O comportamento fica centralizado no lib-auth de propósito, pra qualquer serviço reusar.Como
token_jwt_key.pemdo Casdoor). Sem round-trip de rede, sem dependência do SDK do Casdoor — cada consumidor injeta o cert do seu próprio issuer.NewM2MAuthenticator(certificatePEM, enabled, logger): quandoenabled=falseé pass-through (dev/local); quandoenabled=trueexige um PEM parseável na construção (misconfig falha no boot, não em runtime).RequireM2M()expõe a identidade autenticada (sub,azp) viaM2MSubjectFromContext/M2MClientIDFromContextpros handlers downstream.Postura de segurança (Opção B — decidida)
Autentica, não autoriza. RS256 é pinado (fecha alg-substitution
none/HS256),expé obrigatório, e otypetem que serapplication. Não faz RBAC e não amarra o chamador ao{slug}— essa checagem de posse é intencionalmente fora de escopo: a application M2M é provisionada manualmente por um operador confiável, e possuir um token M2M válido é a fronteira de confiança aceita. Hardening de posse (app↔slug) fica anotado como evolução futura.Falhas (todas fail-closed)
exptype != application(ex.: normal-user)subTestes & qualidade
none, expirado, semexp, tipo errado,subausente, malformado, nil-key, pass-through desabilitado, e o caminho completo viaapp.Testdo Fiber.go build/vet/test/golangci-lintverdes.Próximo passo (outro repo)
Ao mergear, o semantic-release corta uma nova
v3.xbeta. Oplugin-access-manager(componenteidentity) então faz o bump e plugaRequireM2M()como 1º handler da rotaPUT /v1/declarations/:slug, passando o cert Casdoor embedado.🤖 Generated with Claude Code