Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix(authn/oidc): refresh JWKS on unknown kid to handle key rotation#3101

Merged
poovamraj merged 6 commits into
openfga:mainopenfga/openfga:mainfrom
andrey-berenda:fix/oidc-jwks-refresh-unknown-kidandrey-berenda/openfga:fix/oidc-jwks-refresh-unknown-kidCopy head branch name to clipboard
May 14, 2026
Merged

fix(authn/oidc): refresh JWKS on unknown kid to handle key rotation#3101
poovamraj merged 6 commits into
openfga:mainopenfga/openfga:mainfrom
andrey-berenda:fix/oidc-jwks-refresh-unknown-kidandrey-berenda/openfga:fix/oidc-jwks-refresh-unknown-kidCopy head branch name to clipboard

Conversation

@andrey-berenda

@andrey-berenda andrey-berenda commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Set RefreshUnknownKID: true on the keyfunc.Options used to build the JWKS, so the cache is refetched when a token arrives with a kid that is not currently cached. This is the standard mitigation for issuer key rotation (e.g. AWS EKS rotates every 7 days, which is longer than the 48h periodic refresh).
  • Set RefreshRateLimit: 1 * time.Minute to protect the issuer from a refresh storm if tokens with unknown kids arrive in bursts. This pairing is recommended by the keyfunc docs whenever RefreshUnknownKID is enabled.

Without RefreshUnknownKID, when an issuer evicts an old key from the JWKS between OpenFGA's 48h refreshes, valid tokens signed with the new key are rejected with invalid claims until the next periodic refresh or a process restart. See #3099 for the full failure mode and an EKS-specific reproduction.

Closes #3099

Test plan

  • go build ./...
  • go test ./internal/authn/oidc/... — existing OIDC tests still pass
  • In a deployment with a rotating issuer (e.g. EKS), confirm that after the issuer evicts the old signing key, OpenFGA accepts tokens signed with the new key without a restart

Summary by CodeRabbit

  • Bug Fixes

    • OIDC authentication now tolerates issuer key rotation: valid tokens signed with newly published keys are accepted after an automatic JWKS refresh, with refreshes rate-limited to once per minute.
  • Tests

    • Added integration-style tests validating JWKS refresh-on-unknown-key behavior and the refresh rate limit.
  • Documentation

    • Changelog updated to document the OIDC fix.

Copilot AI review requested due to automatic review settings April 30, 2026 07:36
@andrey-berenda
andrey-berenda requested a review from a team as a code owner April 30, 2026 07:36
@linux-foundation-easycla

linux-foundation-easycla Bot commented Apr 30, 2026

Copy link
Copy Markdown

CLA Signed

The committers listed above are authorized under a signed CLA.

@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a57ada0b-fa6c-435a-89ae-5c87d45c704a

📥 Commits

Reviewing files that changed from the base of the PR and between bd48e0c and e5bf40d.

📒 Files selected for processing (1)
  • CHANGELOG.md
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

📝 Walkthrough

Walkthrough

Enables JWKS refresh when a JWT arrives with an unknown kid by setting RefreshUnknownKID: true and adding a RefreshRateLimit (1 minute) to the keyfunc JWKS options; includes HTTP-backed integration tests validating refresh and rate-limiting behavior and updates the changelog.

Changes

OIDC JWKS Refresh on Unknown Key ID

Layer / File(s) Summary
JWKS options initialization
internal/authn/oidc/oidc.go
keyfunc.Get options now include RefreshUnknownKID: true and RefreshRateLimit: jwkRefreshRateLimit (1 minute) while retaining RefreshInterval (48h).
Test harness and imports
internal/authn/oidc/oidc_test.go
Expanded imports for base64url/JWK encoding, JSON, big.Int, and httptest; added concurrency-safe helpers and counters for JWKS endpoint hits.
Refresh-on-unknown-kid integration test
internal/authn/oidc/oidc_test.go (lines ~550–599)
TestRemoteOidcAuthenticator_RefreshUnknownKID boots an authenticator against a mutable JWKS, verifies a token for an initial kid, rotates the JWKS to add a new kid, and asserts a token using the new kid is accepted after the JWKS cache refresh and that the JWKS endpoint was re-requested.
Rate-limit validation test
internal/authn/oidc/oidc_test.go (lines ~601–651)
TestRemoteOidcAuthenticator_RefreshRateLimit temporarily lowers jwkRefreshRateLimit, sends many tokens with distinct unknown kids, and asserts JWKS re-fetches are bounded to exactly one extra endpoint hit within the configured window.
JWKS test utilities
internal/authn/oidc/oidc_test.go (lines ~653–726)
Adds rsaPublicKeyToJWK, jwksTestServer with newJWKSTestServer, setKey, hits, close, and withRealFetchJWK to serve/mutate JWKS, expose OpenID config, and atomically count JWKS endpoint hits.
Changelog entry
CHANGELOG.md
Adds [Unreleased] ### Fixed note documenting enabling JWKS refresh on unknown kid with a 1-minute rate limit (PR #3101).

Sequence Diagram

sequenceDiagram
    participant Client as Client (token w/ new kid)
    participant Keyfunc as keyfunc Library
    participant Cache as Local JWKS Cache
    participant Issuer as Issuer JWKS Endpoint

    Client->>Keyfunc: Validate token (kid unknown)
    Keyfunc->>Cache: Lookup kid
    Cache-->>Keyfunc: kid not found

    Note over Keyfunc,Issuer: RefreshUnknownKID = true\nRefreshRateLimit = 1min

    Keyfunc->>Keyfunc: Check rate limit
    alt allowed
        Keyfunc->>Issuer: Fetch JWKS
        Issuer-->>Keyfunc: JWKS (contains new kid)
        Keyfunc->>Cache: Update cache
    else blocked
        Keyfunc-->>Client: Reject or continue without refresh
    end

    Keyfunc->>Cache: Lookup kid
    Cache-->>Keyfunc: kid found
    Keyfunc-->>Client: Token validated
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • cikasfm
  • adriantam

Poem

🐇 I nibble keys and watch them spin,
When new kids hop, I fetch again,
A minute pause keeps storms at bay,
Then tokens dance and hop my way,
Certified hops—authentication wins.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: enabling JWKS refresh when unknown kid is encountered to handle key rotation scenarios.
Linked Issues check ✅ Passed The PR directly addresses issue #3099 requirements: enables RefreshUnknownKID, sets RefreshRateLimit to 1 minute, maintains RefreshInterval at 48h, adds comprehensive tests, and updates CHANGELOG.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #3099 objectives: JWKS configuration update, test additions for refresh behavior validation, and changelog documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves OIDC JWKS handling to better tolerate issuer key rotation by enabling refresh-on-unknown-kid with rate limiting, reducing the chance of rejecting otherwise valid tokens between periodic refreshes.

Changes:

  • Enable RefreshUnknownKID in keyfunc.Options so JWKS is refetched when an unseen kid appears.
  • Add a RefreshRateLimit to avoid refresh storms when unknown kids arrive in bursts.

Comment thread internal/authn/oidc/oidc.go
Set RefreshUnknownKID so the JWKS is refetched when a token arrives
with a kid that is not in the cache. Without this, after an issuer
rotates and evicts an old signing key (e.g. AWS EKS, which rotates
every 7 days), valid tokens are rejected with "invalid claims" until
the next 48h periodic refresh or a process restart.

Also set RefreshRateLimit to protect the issuer from refresh storms
when tokens arrive with unknown kids, as recommended by the keyfunc
docs whenever RefreshUnknownKID is enabled.

Closes openfga#3099
@andrey-berenda
andrey-berenda force-pushed the fix/oidc-jwks-refresh-unknown-kid branch from 7958851 to 817b758 Compare April 30, 2026 07:41
@poovamraj

Copy link
Copy Markdown
Contributor

@coderabbitai

@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@poovamraj, it looks like your comment didn't include a specific request. How can I help you with PR #3101? Here are some things I can do:

  • Review the PR – Trigger a full review of the changes.
  • Answer questions – Explain the changes or their implications.
  • Generate a summary – Regenerate the AI-generated PR summary.
  • Search the codebase – Look into related code or dependencies.
  • Open a follow-up issue – If there's something to track separately.

Just let me know what you need! 😊

@poovamraj

Copy link
Copy Markdown
Contributor

@andrey-berenda looks like we are reusing functionality from underlying library which is great. Can you add tests to verify the behaviour and also update CHANGELOG.md section?

@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.39%. Comparing base (8c9e0bf) to head (e5bf40d).

❌ Your project check has failed because the head coverage (80.39%) is below the target coverage (85.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3101      +/-   ##
==========================================
+ Coverage   80.04%   80.39%   +0.35%     
==========================================
  Files         191      196       +5     
  Lines       20719    21782    +1063     
==========================================
+ Hits        16583    17509     +926     
- Misses       3415     3503      +88     
- Partials      721      770      +49     
Flag Coverage Δ
matrix 84.83% <ø> (?)
storage 86.28% <ø> (ø)
unit 79.16% <100.00%> (+0.14%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@poovamraj

poovamraj commented May 11, 2026

Copy link
Copy Markdown
Contributor

Adding info from documentation:

// RefreshUnknownKID indicates that the JWKS refresh request will occur every time a kid that isn't cached is seen.
// This is done through a background goroutine. Without specifying a RefreshInterval a malicious client could
// self-sign X JWTs, send them to this service, then cause potentially high network usage proportional to X. Make
// sure to call the JWKS.EndBackground method to end this goroutine when it's no longer needed.
//
// It is recommended this option is not used when in MultipleJWKS. This is because KID collisions SHOULD be uncommon
// meaning nearly any JWT SHOULD trigger a refresh for the number of JWKS in the MultipleJWKS minus one.

// RefreshRateLimit limits the rate at which refresh requests are granted. Only one refresh request can be queued
// at a time any refresh requests received while there is already a queue are ignored. It does not make sense to
// have RefreshInterval's value shorter than this.

Adds integration-style tests against a real httptest JWKS endpoint to
verify the new RefreshUnknownKID behavior picks up rotated keys and that
RefreshRateLimit bounds refreshes to one per window. Also adds a
CHANGELOG entry for the fix.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
internal/authn/oidc/oidc_refresh_test.go (3)

57-57: 💤 Low value

Consider logging JSON encoding errors in test handlers.

While ignoring errors is acceptable in test code, if JSON encoding fails silently, it could make debugging test failures more difficult. Consider at least logging or failing the test if encoding fails.

🔍 Proposed fix to log encoding errors
-		_ = json.NewEncoder(w).Encode(map[string]any{"keys": jwkList})
+		if err := json.NewEncoder(w).Encode(map[string]any{"keys": jwkList}); err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}

And similarly for line 61:

-		_ = json.NewEncoder(w).Encode(map[string]string{
+		if err := json.NewEncoder(w).Encode(map[string]string{
 			"issuer":   j.server.URL,
 			"jwks_uri": j.server.URL + "/jwks",
-		})
+		}); err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}

Also applies to: 61-61

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/authn/oidc/oidc_refresh_test.go` at line 57, The test HTTP handler
currently calls json.NewEncoder(w).Encode(map[string]any{"keys": jwkList}) and
ignores the returned error; update the handler to capture the error from
json.NewEncoder(w).Encode(...) and either fail the test (t.Fatalf) or at minimum
log the error (t.Logf) so JSON encoding problems are visible during test
failures—apply the same change for the second occurrence on line 61; reference
the json.NewEncoder(w).Encode call and the jwkList/w variables when making the
change.

183-184: 💤 Low value

Consider a more deterministic wait mechanism.

The fixed 200ms sleep is a brittle synchronization mechanism that could be flaky on slow CI systems. While this pattern is common in rate-limit tests, consider whether the test could use a longer require.Eventually check or verify the refresh count hasn't changed over multiple samples instead of relying on a fixed sleep duration.

That said, this is a minor concern and the current approach is acceptable for most environments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/authn/oidc/oidc_refresh_test.go` around lines 183 - 184, The test
uses a brittle fixed sleep (time.Sleep(200 * time.Millisecond)) to wait for any
extra refreshes; replace this with a deterministic check such as
require.Eventually (from testify) that polls the observed refresh count and
asserts it does not increase for a short window, or sample the refresh count
multiple times and assert stability; locate the time.Sleep(200 *
time.Millisecond) call in oidc_refresh_test.go and change it to a
require.Eventually/assert loop that inspects the refresh counter (the variable
tracking refreshes in the test) to ensure no new refreshes occur within the
chosen timeout.

150-152: ⚡ Quick win

Consider extracting rate-limit configuration to avoid global variable mutation in tests.

The test mutates the package-level jwkRefreshRateLimit variable. While the cleanup pattern is correct and other tests in this package do not currently access this variable, global state mutation in tests is a code smell that could become problematic if future tests add t.Parallel() or access this variable.

If the code under test supports dependency injection, consider passing the rate limit as a test-specific parameter instead of modifying the global variable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/authn/oidc/oidc_refresh_test.go` around lines 150 - 152, The test
mutates the package-global jwkRefreshRateLimit; instead, modify the production
code to accept the refresh rate via dependency injection (e.g., add a
constructor/option parameter on the refresher/manager used in
oidc_refresh_test.go or add NewRefresher(rateLimit time.Duration) that stores a
per-instance value) and update the test to pass a short test-specific duration
rather than changing jwkRefreshRateLimit; alternatively, provide a package-level
setter like SetJWKRefreshRateLimitForTests(rate time.Duration) and use it only
if you can't refactor, but prefer adding a per-instance field and changing the
code paths that reference jwkRefreshRateLimit to read that field (identify
usages of jwkRefreshRateLimit and the refresher/refresh function in
oidc_refresh_test.go to update).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/authn/oidc/oidc_refresh_test.go`:
- Line 57: The test HTTP handler currently calls
json.NewEncoder(w).Encode(map[string]any{"keys": jwkList}) and ignores the
returned error; update the handler to capture the error from
json.NewEncoder(w).Encode(...) and either fail the test (t.Fatalf) or at minimum
log the error (t.Logf) so JSON encoding problems are visible during test
failures—apply the same change for the second occurrence on line 61; reference
the json.NewEncoder(w).Encode call and the jwkList/w variables when making the
change.
- Around line 183-184: The test uses a brittle fixed sleep (time.Sleep(200 *
time.Millisecond)) to wait for any extra refreshes; replace this with a
deterministic check such as require.Eventually (from testify) that polls the
observed refresh count and asserts it does not increase for a short window, or
sample the refresh count multiple times and assert stability; locate the
time.Sleep(200 * time.Millisecond) call in oidc_refresh_test.go and change it to
a require.Eventually/assert loop that inspects the refresh counter (the variable
tracking refreshes in the test) to ensure no new refreshes occur within the
chosen timeout.
- Around line 150-152: The test mutates the package-global jwkRefreshRateLimit;
instead, modify the production code to accept the refresh rate via dependency
injection (e.g., add a constructor/option parameter on the refresher/manager
used in oidc_refresh_test.go or add NewRefresher(rateLimit time.Duration) that
stores a per-instance value) and update the test to pass a short test-specific
duration rather than changing jwkRefreshRateLimit; alternatively, provide a
package-level setter like SetJWKRefreshRateLimitForTests(rate time.Duration) and
use it only if you can't refactor, but prefer adding a per-instance field and
changing the code paths that reference jwkRefreshRateLimit to read that field
(identify usages of jwkRefreshRateLimit and the refresher/refresh function in
oidc_refresh_test.go to update).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 30ce67c8-8a12-415b-a601-4e95ec81cca6

📥 Commits

Reviewing files that changed from the base of the PR and between 817b758 and 910ace3.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • internal/authn/oidc/oidc_refresh_test.go
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

Moves the new RefreshUnknownKID and RefreshRateLimit tests (plus the
jwksTestServer helper) into the existing oidc_test.go so all OIDC tests
live in one file.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/authn/oidc/oidc_test.go`:
- Around line 608-633: The test is nondeterministic because
generateJWTSignatureKeys() is called inside the burst loop; pre-generate all RSA
private keys (or reuse a single private key) outside the for-loop and then use
those keys when creating tokens to avoid RSA keygen timing affecting the
jwkRefreshRateLimit window; update the loop that currently creates privKey via
generateJWTSignatureKeys() to instead reference precomputed privKeys and keep
the rest of the logic (generateJWT(..., fmt.Sprintf("unknown_kid_%d", i), ...),
oidc.Authenticate) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1c39b12b-88e2-49ce-a220-6895b6341eae

📥 Commits

Reviewing files that changed from the base of the PR and between 910ace3 and 6a80483.

📒 Files selected for processing (1)
  • internal/authn/oidc/oidc_test.go

Comment thread internal/authn/oidc/oidc_test.go
…test

RSA keygen latency inside the burst loop could chew into the
jwkRefreshRateLimit window and make the test flaky. Move keygen and JWT
signing before the burst so only Authenticate calls happen inside it.
Signatures aren't validated for the unknown kids in this test (the JWKS
doesn't contain them), so one shared private key is enough. Generating
one key instead of five keeps the burst comfortably inside the
jwkRefreshRateLimit window.
@poovamraj

Copy link
Copy Markdown
Contributor

Adding context about the convo had in CNCF OpenFGA slack channel for future reference
Screenshot 2026-05-12 at 8 16 38 PM

poovamraj
poovamraj previously approved these changes May 13, 2026
@poovamraj
poovamraj merged commit 857e432 into openfga:main May 14, 2026
25 of 26 checks passed
@andrey-berenda
andrey-berenda deleted the fix/oidc-jwks-refresh-unknown-kid branch June 6, 2026 05:46
fredrikaverpil added a commit to fredrikaverpil/openfga that referenced this pull request Jul 12, 2026
Add support for exporting logs via OTLP, allowing integration with any
OpenTelemetry-compatible backend (Grafana Loki, Datadog, GCP Cloud
Logging, etc.).

When log.otlp.enabled is set, logs are exported via OTLP in addition to
stdout. The otelzap bridge attaches span context (trace ID, span ID) to
each log record, enabling log-trace correlation in backends that
support it.

Configuration mirrors the trace configuration shape: the standard OTel
env vars (OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_ENDPOINT)
only answer where logs are sent, while the explicit OpenFGA flag
(log.otlp.enabled / --log-otlp-enabled / OPENFGA_LOG_OTLP_ENABLED)
answers whether to export at all — so a cluster that injects the
generic endpoint variable for tracing does not silently start exporting
logs on upgrade.

zap's production sampling is applied outside the tee, so the keep/drop
decision is made once, before fan-out: stdout and OTLP receive the same
deterministically sampled stream and collector egress stays bounded
during log storms.

Changes:
- Add otelzap bridge core backed by an OTLP log provider
  (internal/telemetry/logging.go)
- Add WithOTELCore logger option that tees log entries to the bridge.
  The bridge core is capped to the configured log level, the stdout
  core strips the bridge-only context field via contextFilterCore, and
  the sampler wraps the tee (pkg/logger/logger.go)
- Attach the context field in the *WithContext logging methods only
  when an OTEL core is configured, and use those methods in the gRPC
  logging interceptor so the bridge can extract span context
  (pkg/middleware/logging/logging.go)
- Add config: log.otlp.enabled, log.otlp.endpoint, log.otlp.tls.enabled
  with OPENFGA_LOG_OTLP_* env vars and OTEL_EXPORTER_OTLP_* endpoint
  fallbacks (pkg/server/config/config.go, cmd/run/, .config-schema.json)

feat: add potential v2 breaking change logs for Expand and ListUsers (openfga#3182)
release: update changelog for release 1.18.1 (openfga#3188)
release: Update changelog to prep for 1.18.1 release (openfga#3186)
test: fix flaky TestV2CheckWithIteratorCache_HigherConsistencyBypassesCache (openfga#3061)

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Merge commit from fork

* test reproducing ListUsers report

* implement fix

* additional test with 3 operands
fix: match IPv4-mapped IPv6 addresses in the in_cidr condition (openfga#3181)

Signed-off-by: kanywst <niwatakuma@icloud.com>
fix: use deterministic proto marshaling for stored authorization models (openfga#3171)
chore: create draft release and publish after provenance succeeds for immutable tags/releases (openfga#3178)
docs: fix changelog entry (openfga#3177)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
feat: add v2Check logs for resolution breaking change (openfga#3149)
feat: BatchCheck uses v2Check when ExperimentalWeightedGraphCheck is enabled (openfga#3154)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore: update changelog to add CVE identifiers for recent fixes (openfga#3176)
chore: update todo comment string in migration guide (openfga#3175)
release: update changelog for release `v1.18.0` (openfga#3174)

Co-authored-by: adriantam <adrian.tam@okta.com>
Merge commit from fork

* fix(authn): require issuer and audience when OIDC authn is enabled

Enforce configuration authn.oidc.audience and authn.oidc.issuer when
`authn.method` is set to `oidc`.

* fixed based on code review feedback

* fix: adding comments + test case on empty space for audience

* update based on code review feedback

* Update CHANGELOG.md

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>

* update changelog

* Update CHANGELOG.md

---------

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Merge commit from fork

* fix(mysql): collate identifier columns as utf8mb4_bin

* fix: add operator note to changelog

* fix: move tests to shared storage

* fix: separate migrations for each table

* fix: add runbook for migrations

* fix: set lock_wait_timeout

* fix: add docker instructions

* fix: add docker instructions

* fix: combine the migrations back into one, fix documentation for this

* fix: include details about table copy and

* Update CHANGELOG.md

Co-authored-by: Adrian Tam <adrian.tam@okta.com>

---------

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
fix: use constant-time comparison for preshared key authentication (openfga#3168)
chore(deps): bump the dependencies group with 2 updates (openfga#3166)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
chore(deps): bump the dependencies group with 2 updates (openfga#3167)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
release: update changelog for release `v1.17.1` (openfga#3165)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore: bump grpc-health-probe to v0.4.52 (openfga#3164)

Co-authored-by: Saad Hussain <saad.hussain@okta.com>
docs: update caching docs (openfga#3163)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: continuation token deserializer - handle `|` in type names (openfga#3152)
chore(deps): bump the dependencies group across 1 directory with 13 updates (openfga#3162)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
chore(deps): bump the dependencies group across 1 directory with 10 updates (openfga#3156)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
fix: use query start time as iterator cache entry LastModified to prevent stale-read survival (openfga#3155)
chore(deps): bump grpc-ecosystem/grpc-health-probe from v0.4.50 to v0.4.51 in the dependencies group (openfga#3157)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
chore: Bump go toolchain to 1.26.4 (openfga#3159)
fix: prevent v2Check from falling back for throttling and validation (openfga#3150)
ci: make pr benchmark comparisons less fragile (openfga#3153)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
release: update changelog for release `v1.17.0` (openfga#3151)

Co-authored-by: Vic-Dev <vmichellej@gmail.com>
refactor: redesign cache key generation, making it more secure and consistent (openfga#3148)
feat: add configurable trace sampler with ParentBased support (openfga#3072)
release: update changelog for release `v1.16.1` (openfga#3147)
chore: update grpc-health-probe to latest to addres std lib CVEs (openfga#3146)
fix: skip v2Check weight2 pruning if iterator is unordered (openfga#3145)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore: add concurrency-group to PR-related CI steps (openfga#3140)
docs: move OIDC JWKS refresh entry from v1.15.1 to v1.16.0 (openfga#3142)
fix: when v2Check is primary algorithm, fix fallback condition and emit metrics (openfga#3141)
release: update changelog for release `v1.16.0` (openfga#3139)
Merge commit from fork

* fix: Standardize cache key generation everywhere

* Revert "fix: Standardize cache key generation everywhere"

This reverts commit ce60c6f9ae48a310a4dea2b824b5993520c8ba1c.

* length-encoded approach

* Revert "length-encoded approach"

This reverts commit b94637c187c57a2d3f3904247267bbc8ad21a41a.

* implement Hexer() and use in some cache keys

* appendConditionsHash -> generateConditionsHash

* mv Hexer -> BuildKey

* BuildKey -> BuildCacheKey

refactor to BuildCacheKey on each individual prefix component to remove collision risk

* make v2 cacheKey functions the standard

* make cache key prefixes consistent

* generateConditionsHash -> generateConditionsString

* delimit condition name string

* remove extra empty check

* relocate and reuse existing userTypeRestrictions function

* replace hashing of conditions for brevity

* fix tests

* cleanup, add test file

* remove unused slice capacity

* make prefix treatments consistent

* add nil-byte separator in object ids

* hash user type restrictions for brevity

* update comment string, use nil-byte separator for future-proofing

* remove call to xxhash.new

* adjustments for performance, consistency, and interface ergonomics.

* make condition hash generation more efficient.

* add clarifying comments for size caluculations

* fix builder growth calculations to match original intentions

* update outdated comment

* don't hash potentially zero values

* Revert "don't hash potentially zero values"

This reverts commit 2ad6c5b796bc20a82c1414c5146c3c708330eefa.

* add condition key separator unconditionally

* patch test expectations for new key structure

* export V2IteratorCachePrefix, use in tests

---------

Co-authored-by: justin <justin.cohen@okta.com>
Co-authored-by: Joshua Jones <joshua.jones@okta.com>
fix: unintentional zeroing of slice values by setting slice to nil (openfga#3135)
increase the check v2 trace information fidelity (openfga#3134)
feat: add datastore ping and ping retry configurations (openfga#3113)
fix: prevent v2Check strategies returning spurious false on context cancellation (openfga#3128)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix(authn/oidc): refresh JWKS on unknown kid to handle key rotation (openfga#3101)
fix: v2Check falls back to v1 on errors (openfga#3126)
fix: don't cache false results from cancelled-context goroutines in v2Check (openfga#3125)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
make union cache key unique by including the node input's label (openfga#3117)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Saad Hussain <saad.hussain@okta.com>
fix: shadow v2check and check use the same trace (openfga#3118)
fix: bump go toolchain version to 1.26.3 (openfga#3115)
chore: add more spans/attributes to v1 and v2 Check (openfga#3116)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: add matches attribute to shadowv2Check and Check spans (openfga#3114)
fix: use the same `request_id` for shadow traces in v2Check (openfga#3110)
release: update changelog for release `v1.15.1` (openfga#3112)
feat: reuse MySQL container across tests (openfga#3042)
fix: close all channels opened thus far, before return on error (openfga#3111)
chore: Add more spans/attributes to v2Check (openfga#3102)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: ensure acquired limiter token is released on throttle context cancelation (openfga#3106)
fix: cancel context before waiting on worker pool in ResolveUnionEdges (openfga#3105)
fix: replace golang.org/x/exp/maps with stdlib maps to resolve govet inline errors (openfga#3104)
fix: v2Check EdgeCacheKey collisions (openfga#3097)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
fix: expose context errors when they can be the potential cause of an underlying datastore error (openfga#3096)
chore(deps): bump the dependencies group across 1 directory with 2 updates (openfga#3093)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: move subproblem cache lookup from ResolveUnionEdges into ResolveUnion (openfga#3095)
chore(deps): bump the dependencies group with 4 updates (openfga#3092)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: error handler panic (openfga#3091)
release: update changelog for release `v1.15.0` (openfga#3090)
chore(deps): bump the dependencies group across 1 directory with 4 updates (openfga#3087)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: v2Check correctly uses query cache even when cache controller is disabled (openfga#3086)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
chore(deps): bump the dependencies group across 1 directory with 7 updates (openfga#3081)

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump github.com/jackc/pgx/v5 from 5.9.1 to 5.9.2 (openfga#3085)

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump grpc-ecosystem/grpc-health-probe from v0.4.47 to v0.4.48 in the dependencies group across 1 directory (openfga#3065)

Signed-off-by: dependabot[bot] <support@github.com>
feat: try to use UDS internally between HTTP server and gRPC server (openfga#2937)
feat: add jitter to internal cache TTLs to prevent thundering herd effects (openfga#3033)

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
list objects pipeline edge pruning (openfga#3075)
update toolchain go to 1.26.2 to address stdlib CVEs (openfga#3084)
chore: add store ID and datastore query/item count to shadowV2Check log (openfga#3073)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
CI speed up (openfga#3062)

Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Co-authored-by: Joshua Jones <joshua.jones@okta.com>
Add tracing to v2 Check planner strategy selection (openfga#3077)
fix: v2Check honours `check-query-cache-enabled` flag (openfga#3070)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
feat: reuse PostgreSQL container across tests (openfga#3018)
chore: fix reporter links in changelog (openfga#3069)
release: update changelog for release `v1.14.2` (openfga#3068)
fix: add null byte delimiter in contextual tuple cache keys and validation in v2Check (openfga#3064)
release: update changelog for release `v1.14.1` (openfga#3060)
chore(deps): bump the dependencies group across 1 directory with 7 updates (openfga#3056)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
fix: use a baseURL for AuthZEN configuration endpoint (openfga#3057)
chore: replace docker with moby (openfga#3047)
Iterator Cache V2: Storage Wrapper Pattern with Lock-Free Design (openfga#3016)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
test: fix flaky condition test (openfga#3058)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
chore(deps): bump the dependencies group across 1 directory with 6 updates (openfga#3045)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
chore(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.41.0 to 1.43.0 (openfga#3054)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
feat: add graceful shutdown timeout configuration (openfga#2976)
chore: update changelog to reflect playground off-by-default behavior (openfga#3053)
chore: decouple Error() and Unwrap() (openfga#3051)
perf: remove `fmt` from cache key generation (openfga#3006)
perf: enhancements for list objects (openfga#3043)
chore: remove stale notice file (openfga#3050)
docs: update 1.14.0 for CVE fix (openfga#3046)
feat: Add datastore throttling & concurrency limiting to v2Check (openfga#3035)

Signed-off-by: Saad Hussain <saad.hussain@okta.com>
release: update changelog for release `v1.14.0` (openfga#3040)
batch check cache (openfga#3025)
Merge commit from fork

Also prevent enabling playground when the server requires authentication
feat: add stats on tuple iterator query (openfga#3030)
fix: remove unnecessary non-deterministic test (openfga#3038)
remove unnecessary import (openfga#3032)
perf: improve the intersection algorithm, reducing latency and memory use (openfga#3031)
fix: ListObjects pipeline algorithm enhancements and fix for potential deadlock (openfga#3028)
chore: Also update openfga/helm-charts in release script (openfga#3010)
chore: update CICD to enforce GRPC healthprobe changes (openfga#2990)
fix: SQL `TupleOperation` serialization and `pgx.ErrNoRows` error handling (openfga#3014)
docs: update changelog for CVE-2026-33729 (openfga#3017)
chore: output the diff after running keep-a-changelog (openfga#3015)
chore(deps): bump the dependencies group across 1 directory with 11 updates (openfga#2998)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
chore(deps): bump the dependencies group across 1 directory with 10 updates (openfga#2999)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
release: update changelog for release `v1.13.1` (openfga#3002)
Merge commit from fork

* strip unicode control characters, encode context key length in cache key

* add cache_key tests to ensure we escape control characters and encode context key length

* run linter

* docs: update changelog

* Apply suggestion from @adriantam

Co-authored-by: Adrian Tam <adrian.tam@okta.com>

* Apply suggestion from @adriantam

Co-authored-by: Adrian Tam <adrian.tam@okta.com>

---------

Co-authored-by: Saad Hussain <saad.hussain@okta.com>
Co-authored-by: Saad Hussain <saad.h@outlook.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
release: update changelog for release `v1.13.0` (openfga#2997)
refactor: Separate caches for v1 and v2 Check (openfga#2968)

Co-authored-by: Justin Cohen <justincoh@gmail.com>
docs: fix typos in comments (openfga#2972)

Signed-off-by: Artem Muterko <artem@sopho.tech>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
observability: aggregate message statistics for each list-objects sender into a single span (openfga#2993)

Co-authored-by: Justin Cohen <justincoh@gmail.com>
fix: capture panics in pipeline's base resolver, and return as errors. (openfga#2994)
docs: fix typos in RELEASES.md and Makefile (openfga#2980)

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
AuthZen v1.0 Implementation (openfga#2875)

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rokibul Hasan <mdrokibulhasan@appscode.com>
Signed-off-by: Vihang Mehta <vihang@gimletlabs.ai>
Co-authored-by: Karl Persson <kalle.persson92@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Maria Ines Parnisari <maria.inesparnisari@okta.com>
Co-authored-by: Rokibul Hasan <mdrokibulhasan18@gmail.com>
Co-authored-by: José Padilla <jose.padilla@okta.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
Co-authored-by: Vihang Mehta <vihang@gimletlabs.ai>
Co-authored-by: Joshua Jones <joshua.jones.software@gmail.com>
Co-authored-by: Justin Cohen <justincoh@gmail.com>
release: update changelog for release `v1.12.1` (openfga#2992)
chore(deps): bump google.golang.org/grpc from 1.79.1 to 1.79.3 (openfga#2988)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
chore: enforce minor version upgrade rule (openfga#2978)

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
perf: tuple validation performance tweaks (openfga#2984)
fix: support URI schemes in OTLP endpoint configuration (openfga#2981)
refactor: remove custom pipes and replace with channels (openfga#2977)
chore(docs): added caching  docs (openfga#2664)

Co-authored-by: Saad Hussain <saad.hussain@okta.com>
release: update changelog for release `v1.12.0` (openfga#2974)
chore: update toolchain go to 1.26.1 (openfga#2975)
fix: update toolchain go to 1.25.8 to address stdlib CVEs (openfga#2971)
fix: correct swapped format args in DecodeParameterType error message (openfga#2961)

Signed-off-by: Artem Muterko <artem@sopho.tech>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
perf: small tweaks to tuple validation functions (openfga#2963)

Co-authored-by: Vic-Dev <vmichellej@gmail.com>
test: add tests for condition parameter type any with complex context structures (openfga#2959)

Signed-off-by: Artem Muterko <artem@sopho.tech>
test: add functional test for ReadAssertions API endpoint (openfga#2960)

Signed-off-by: Artem Muterko <artem@sopho.tech>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
make configurable the maximum received grpc message size (openfga#2952)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
fix: set ExperimentalPipelineListObjects in experimentals by default (openfga#2957)

fix: `cache_item_count` metric overcounting (openfga#2950)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
chore(deps): bump the dependencies group across 1 directory with 7 updates (openfga#2953)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
refactor: Make shadowV2Check final log clearer (openfga#2946)

Move telemetry package to internal/telemetry (openfga#2938)

Signed-off-by: Oleksandr Shestopal <ar.shestopal-oshegithub@gmail.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
chore(deps): bump the dependencies group across 1 directory with 3 updates (openfga#2956)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: Resolve race condition in check reducers (openfga#2947)

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
fix: gateway grpc client tls cert rotation (openfga#2951)

Signed-off-by: Shashank Goel <goelshashank13@gmail.com>
fix: disable LO pipeline if ff has it set for a store (openfga#2945)

chore(deps): bump the dependencies group across 1 directory with 4 updates (openfga#2949)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fix: various random fixes (openfga#2942)

refactor: check using weighted graph (openfga#2816)

Co-authored-by: Yissell Garma <yissell.garma@okta.com>
release: update changelog for release `v1.11.6` (openfga#2939)

feat: enable pipeline algorithm by default (openfga#2921)

add tests to exercise reported bug (openfga#2934)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Adrian Tam <adrian.tam@okta.com>
refine AGENTS.md to make it more concise with higher value. (openfga#2936)

Co-authored-by: Justin Cohen <justincoh@gmail.com>
migrate grpc dial context to NewClient (openfga#2714)

Co-authored-by: Adrian Tam <adrian.tam@okta.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
chore(deps): bump filippo.io/edwards25519 from 1.1.0 to 1.1.1 (openfga#2935)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OIDC: JWKS cache misses key rotation events because RefreshUnknownKID is not enabled

4 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.