Skip to content

Don't report expired tokens as Sentry errors + harden InitSentry #87

Description

@rappm

In keycloakTokenVerifier/keycloakMiddleware.go, a failed verifier.Verify(...) runs log.Error("Failed to validate token: ", err). Because utils/InitSentry attaches a logrus event hook for Error/Fatal/Panic, every expired token becomes a Sentry issue. Expired tokens are routine (the client refreshes and retries), so this is pure noise across all servers that use AuthenticationMiddleware.

This is the SDK counterpart to the core-only fix in the main repo (issue #1175), where servers/core keeps its own copy of the verifier.

Expired-token fix

go-oidc v3.19.0 returns a typed *oidc.TokenExpiredError from Verify(...), so expiry can be detected precisely (no string matching):

func logTokenVerificationFailure(err error) {
	var expiredErr *oidc.TokenExpiredError
	if errors.As(err, &expiredErr) {
		log.Debug("Rejected expired token: ", err)
		return
	}
	log.Error("Failed to validate token: ", err)
}

Call it at the verifier.Verify failure site in keycloakMiddleware.go (replacing the bare log.Error). Keep it scoped to verification failures only — do not touch the claims-parsing or other auth paths, which may signal malformed/misissued tokens. Debug is below both logrus hooks, so expired tokens reach neither Sentry issues nor Sentry logs.

After release, bump the SDK version and update go.mod across the 6 servers that consume AuthenticationMiddleware.

InitSentry hardening (utils/initSentry.go)

Separate gaps found while reviewing the Sentry setup (not blockers, but worth fixing here since the config lives in the SDK):

  • Set Release from GITHUB_SHA (fall back to GITHUB_REF) — CI already injects these, but sentry.Init never sets Release, so there is no release/regression grouping.
  • Make TracesSampleRate configurable via env (e.g. SENTRY_TRACES_SAMPLE_RATE), defaulting to a low value in prod. It is currently hardcoded to 1.0 (100% transaction sampling).
  • Optional: a beforeSend to drop token-verification events centrally as defense-in-depth.

Note for consumers (not SDK code)

sentrygin.New(sentrygin.Options{}) is installed with the default Repanic: false while servers use gin.Default(). Upstream recommends Repanic: true so Sentry captures the panic and Gin's Recovery still produces the 500. Worth documenting/recommending to consumers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions