OIDC Discovery & JWKS Rotation Monitor avatar

OIDC Discovery & JWKS Rotation Monitor

Pricing

$3.00 / 1,000 successful oidc issuer checks

Go to Apify Store
OIDC Discovery & JWKS Rotation Monitor

OIDC Discovery & JWKS Rotation Monitor

Track public OpenID Connect discovery metadata and JWKS signing-key changes across runs. Emit structured rotation, endpoint, algorithm, and key-overlap signals for scheduled identity operations.

Pricing

$3.00 / 1,000 successful oidc issuer checks

Rating

0.0

(0)

Developer

Maarten Vreeburg

Maarten Vreeburg

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 days ago

Last modified

Categories

Share

Track public OpenID Connect discovery metadata and JSON Web Key Sets (JWKS) between scheduled runs. Each issuer produces one structured dataset row with key identifiers, signing algorithms, a persistent snapshot hash, and review-oriented changes such as key additions/removals, endpoint changes, same-kid key-material changes, and missing required algorithms.

This Actor is for identity/platform, SRE, and integration teams that depend on public third-party identity issuers. It creates a lightweight change ledger that can feed Apify schedules, webhooks, and downstream incident or vendor-management workflows.

It does not validate live tokens, exercise a login flow, refresh your application's own JWKS cache, prevent authentication failures, or prove whether a provider used a safe rotation overlap. Production token validators should still use maintained libraries that refresh keys correctly when an unknown kid appears.

Independent community Actor: This Actor is not affiliated with or endorsed by the OpenID Foundation, Google, Auth0, Okta, Microsoft, Amazon Web Services, or any identity provider whose public endpoints you monitor. Provider metadata remains the provider's source material; verify material identity/security decisions against the provider's documentation and your own runtime telemetry.

Why monitor discovery and JWKS?

OIDC clients commonly discover endpoint URLs and signing keys automatically. That native behavior is essential, but a separate scheduled record can still help teams:

  • notice that a vendor added or removed a published key;
  • review issuer, jwks_uri, authorization, token, revocation, or introspection endpoint changes;
  • detect key material changing while the same kid remains present;
  • check that required signing algorithms are still advertised or represented by current keys;
  • keep a provider-independent history across otherwise ephemeral application caches;
  • route changed rows into an existing Apify integration or webhook workflow.

A monitor is an observability aid, not a replacement for runtime token-validation metrics. Polling can miss brief transitions between checks, so no_key_overlap_observed_between_checks means exactly that—it does not prove that no overlap occurred at any time.

Input

FieldRequiredDescription
monitorIdYesStable ID for one independent watchlist. Reuse it across scheduled runs to retain the same baselines.
targetsYes1–50 public HTTPS OIDC discovery targets. Duplicate discoveryUrl values are checked once.
targets[].discoveryUrlYesFull public .well-known/openid-configuration URL.
targets[].labelNoInternal environment, vendor, or owner label.
targets[].expectedIssuerNoExact issuer value expected in the discovery document. A mismatch is emitted without overwriting the previous successful baseline.
targets[].requiredSigningAlgorithmsNoExact algorithms that should remain advertised or represented by current keys, for example RS256 or ES256.
timeoutSecondsNoPer-request timeout, 5–60 seconds (default 30).
maxConcurrencyNoIssuers processed concurrently, 1–5 (default 3).

The default input checks Google's public OIDC discovery document and JWKS without credentials, so a default run produces a non-empty dataset. Replace the default monitorId and target before creating a production schedule.

Example:

{
"monitorId": "production-external-identity",
"targets": [
{
"label": "Primary workforce IdP",
"discoveryUrl": "https://accounts.google.com/.well-known/openid-configuration",
"expectedIssuer": "https://accounts.google.com",
"requiredSigningAlgorithms": ["RS256"]
}
],
"timeoutSeconds": 30,
"maxConcurrency": 3
}

Output

Every processed target emits one dataset row.

Successful comparison statuses

statusMeaning
initial_snapshotThe first validated discovery/JWKS summary was stored.
unchangedMonitored discovery fields and normalized public-key summaries match the previous successful snapshot.
changedAt least one monitored metadata or key field changed.

Non-billable error statuses

statusMeaning
discovery_fetch_errorDiscovery URL was blocked, unavailable, redirected unsafely, too large, or returned a network/HTTP error.
discovery_validation_errorDiscovery response was invalid, malformed, too deep, or lacked required issuer/jwks_uri fields.
issuer_mismatchThe returned issuer did not exactly match expectedIssuer.
jwks_fetch_errorThe published JWKS URL could not be fetched safely.
jwks_validation_errorJWKS JSON was invalid, empty, oversized, or exposed private/symmetric key fields that the Actor refuses to store.

Common successful fields include:

  • issuer, discovery_url, final_discovery_url, jwks_uri, and final_jwks_uri;
  • authorization_endpoint, token_endpoint, and advertised/key signing algorithms;
  • key_count, signing_key_count, key_ids, key_types, duplicate IDs, and keys without IDs;
  • required_algorithms_missing and requirements_status;
  • content_hash, previous_hash, and state_store_mode;
  • added_key_ids, removed_key_ids, retained_key_ids, and same_kid_material_changed_ids;
  • rotation_pattern, priority counts, change_summary, and bounded changes records.

Rotation-pattern labels

  • initial_snapshot / no_change — baseline or no monitored change.
  • key_addition_or_prepublication — at least one key appeared and none disappeared.
  • key_retirement — at least one key disappeared and none appeared.
  • partial_rotation_with_retained_kid — keys appeared and disappeared while at least one prior kid remained.
  • no_key_overlap_observed_between_checks — keys appeared and disappeared with no shared kid across the two observed snapshots. Polling cannot prove what happened between those snapshots.
  • same_kid_material_changed — a retained kid now has different public key material or metadata and deserves prompt review.
  • metadata_only_change / key_metadata_changed — monitored fields changed outside the simpler rotation patterns.

review_priority values are conservative routing hints (high, review, informational), not security findings or outage predictions.

Persistence and scheduling

Successful normalized snapshots are stored in the named key-value store oidc-jwks-rotation-monitor-state-v1. The Actor does not rely on the default run-scoped store. Snapshot keys are SHA-256 derivatives of monitorId + discoveryUrl, so stable IDs retain history and separate watchlists do not collide.

Schedule the Actor at a provider-appropriate interval and route changed, error, or requirement rows through Apify integrations. The Actor itself sends no email, DM, chat message, or webhook.

Failed fetches, invalid documents, and issuer mismatches do not overwrite a prior successful baseline.

Charging behavior

The implementation emits one oidc_issuer_check charge event only after both public documents are fetched, validated, normalized, compared, and stored. Invalid URLs, fetch failures, validation failures, and issuer mismatches are not charged. Refer to the live Store listing for the current event price.

The Actor honors Apify run charge limits before emitting the next billed dataset item.

Security and data handling

  • Production input accepts only public HTTPS endpoints on port 443.
  • URL credentials, fragments, control characters, non-ASCII raw URLs, and non-standard ports are rejected.
  • Discovery and JWKS redirects are bounded and revalidated on every hop.
  • DNS is resolved before connecting; every resolved address must be globally routable. The socket connects to that already validated address while TLS certificate validation and SNI still use the original hostname, reducing DNS-rebinding exposure.
  • Private, loopback, link-local, multicast, and reserved destinations are blocked.
  • Discovery responses are capped at 512 KB; JWKS responses are capped at 1 MB; compressed responses are rejected.
  • JSON is capped at 64 nesting levels and 50,000 nodes. Duplicate object fields and non-finite numbers are rejected.
  • JWKS is capped at 100 keys.
  • If a public JWKS contains private RSA/EC parameters or symmetric key material, the Actor rejects it and does not persist or reproduce those fields.
  • Stored state contains normalized discovery fields and public-key fingerprints/summaries, not raw JWKS key material or complete source documents.
  • No authentication-header, cookie, client-secret, token, or private-network input is supported.

Local development

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python smoke_test.py
npx --yes apify-cli validate-schema
npx --yes apify-cli run --purge

The deterministic smoke test uses a process-only local fixture mode and verifies:

  1. initial_snapshot;
  2. unchanged with named-store reuse;
  3. changed after a key rotation and metadata update;
  4. added/removed/retained key IDs and a partial-overlap pattern;
  5. private URL blocking, deep/duplicate JSON rejection, private/symmetric JWK rejection, no-observed-overlap classification, and a one-event PPE charge limit.

The local private-fixture switch is environment-only and is not exposed through Actor input.

Limitations

  • Public endpoints only; private enterprise IdPs and authenticated metadata are intentionally unsupported.
  • The Actor does not download x5u URLs, certificate chains, external references, tokens, or user information.
  • Public JWK fingerprints include the published public JWK object, so metadata-only changes inside a key can alter its fingerprint.
  • A scheduled snapshot cannot observe transitions that occur entirely between runs.
  • Required-algorithm checks are simple exact membership checks, not cryptographic-policy advice.
  • Native OIDC/JWT libraries may already refresh discovery and JWKS caches. This Actor adds an independent scheduled record; it does not modify those caches.