OIDC Discovery & JWKS Rotation Monitor
Pricing
$3.00 / 1,000 successful oidc issuer checks
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
Maintained by CommunityActor 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
kidremains 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
changedrows 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
| Field | Required | Description |
|---|---|---|
monitorId | Yes | Stable ID for one independent watchlist. Reuse it across scheduled runs to retain the same baselines. |
targets | Yes | 1–50 public HTTPS OIDC discovery targets. Duplicate discoveryUrl values are checked once. |
targets[].discoveryUrl | Yes | Full public .well-known/openid-configuration URL. |
targets[].label | No | Internal environment, vendor, or owner label. |
targets[].expectedIssuer | No | Exact issuer value expected in the discovery document. A mismatch is emitted without overwriting the previous successful baseline. |
targets[].requiredSigningAlgorithms | No | Exact algorithms that should remain advertised or represented by current keys, for example RS256 or ES256. |
timeoutSeconds | No | Per-request timeout, 5–60 seconds (default 30). |
maxConcurrency | No | Issuers 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
status | Meaning |
|---|---|
initial_snapshot | The first validated discovery/JWKS summary was stored. |
unchanged | Monitored discovery fields and normalized public-key summaries match the previous successful snapshot. |
changed | At least one monitored metadata or key field changed. |
Non-billable error statuses
status | Meaning |
|---|---|
discovery_fetch_error | Discovery URL was blocked, unavailable, redirected unsafely, too large, or returned a network/HTTP error. |
discovery_validation_error | Discovery response was invalid, malformed, too deep, or lacked required issuer/jwks_uri fields. |
issuer_mismatch | The returned issuer did not exactly match expectedIssuer. |
jwks_fetch_error | The published JWKS URL could not be fetched safely. |
jwks_validation_error | JWKS 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, andfinal_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_missingandrequirements_status;content_hash,previous_hash, andstate_store_mode;added_key_ids,removed_key_ids,retained_key_ids, andsame_kid_material_changed_ids;rotation_pattern, priority counts,change_summary, and boundedchangesrecords.
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 priorkidremained.no_key_overlap_observed_between_checks— keys appeared and disappeared with no sharedkidacross the two observed snapshots. Polling cannot prove what happened between those snapshots.same_kid_material_changed— a retainedkidnow 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.pynpx --yes apify-cli validate-schemanpx --yes apify-cli run --purge
The deterministic smoke test uses a process-only local fixture mode and verifies:
initial_snapshot;unchangedwith named-store reuse;changedafter a key rotation and metadata update;- added/removed/retained key IDs and a partial-overlap pattern;
- 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
x5uURLs, 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.