OAuth and OIDC Provider Metadata Vendor-Intake Gate
Pricing
from $10.00 / 1,000 run_starts
OAuth and OIDC Provider Metadata Vendor-Intake Gate
Writes the security opinion that a vendor-intake review needs before a company connects to a SaaS vendor, an identity provider or a remote MCP server. For each issuer that you name, the Actor reads the public OpenID Connect Discovery or RFC 8414 metadata
Pricing
from $10.00 / 1,000 run_starts
Rating
0.0
(0)
Developer
kingii98
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Write the security opinion that a vendor-intake review needs, before your company connects to a SaaS vendor, an identity provider or a remote MCP server.
You give a list of issuer base URLs. For each issuer the Actor reads the public OpenID Connect Discovery or RFC 8414 metadata document, the published JSON Web Key Set, and the RFC 9728 protected-resource metadata, and it reads the dynamic client registration endpoint. It then gives you one dataset row for each issuer with the endpoints, the declared flows, the key-set defects, a list of findings and an A to F risk grade. Attach that row to your review ticket as the evidence of your written opinion.
The Actor reads public metadata only
- Every request is a GET.
- The Actor sends no credential and no client identifier.
- The Actor starts no login flow.
- The Actor never sends a POST to the registration endpoint, so it never registers a client at the vendor. The registration probe is a plain read that only shows whether the endpoint answers a stranger.
- Only HTTPS is allowed. A URL that carries credentials is refused. A host that resolves to a loopback, private, link-local or otherwise reserved address is refused, and each redirect hop passes the same guard again.
- A refused issuer line does not stop the run. It gets its own dataset row with
the finding
OIDC-DISCOVERY-UNREACHABLE, it is not charged, and the run audits every other line of the list and ends with SUCCEEDED. - No browser, no proxy, no external database and no paid API.
Input
Run the Actor with an empty input to audit the three public identity providers of the default fixture. Every field below has a default.
| Field | Type | Default | What it does |
|---|---|---|---|
issuers | array of strings | three public issuers | 1 to 200 issuer base URLs, for example https://accounts.google.com, or full .well-known metadata URLs. For a base URL the Actor tries the OpenID Connect Discovery path and the RFC 8414 path in turn and keeps the first document that parses. Repeated URLs are read once. |
checks | array of strings | every group | The groups of rules to apply. See the table below. |
baselineKey | string | "" (empty) | Optional name of a stored snapshot, for example Q3 vendor review. Set it to get the changed_since_baseline flag. Leave it empty for a single audit with no stored state. Any name works: the run makes it safe as a record name (see below). |
requestTimeoutSeconds | integer | 15 | How long one HTTPS request may take. Allowed range 5 to 60. |
Check groups
| Group | What it examines |
|---|---|
metadata | The document is reachable, is valid JSON, and its issuer field names the audited URL. This group is always on, because every other group reads the fields of this document. |
transport | Every endpoint URL is HTTPS, and the metadata was served over TLS 1.2 or later. |
pkce | S256 is declared, and the weak plain method is not offered. |
grants | No implicit or hybrid flow, so no token travels in a URL. |
client_auth | The token endpoint does not accept the none client authentication method. |
jwks | The key set is reachable and holds no short RSA key, no unapproved curve, no shared secret, no private key material and no expired certificate. |
registration | Whether the dynamic client registration endpoint answers an anonymous read. |
resource_metadata | Whether the issuer publishes RFC 9728 protected-resource metadata. |
endpoints | Whether the authorization, token, revocation and introspection endpoints are named. |
Switching a group off also stops the requests that only that group needs.
Without jwks the Actor does not read the key set, without registration it
does not probe the registration endpoint, and without resource_metadata it
does not look for the protected-resource document.
Output
The dataset holds one row for each issuer, then one summary row. The row_type
field tells the two apart.
Issuer row (row_type: "issuer")
issuer, discovery_url, http_status, metadata_valid_json,
issuer_matches_url, tls_version, endpoints (an object with
authorization, token, jwks, registration, revocation and
introspection), endpoints_https_only, pkce_s256_supported,
plain_pkce_offered, response_types_supported, implicit_grant_offered,
token_endpoint_auth_methods, none_auth_method_offered, jwks_reachable,
jwks_key_count, weak_or_expired_key_flags,
dynamic_client_registration_open, protected_resource_metadata_present,
findings (each with rule_id, severity, message and evidence_field),
finding_count, highest_severity, risk_grade, changed_since_baseline,
baseline_changes, unreachable and note.
Summary row (row_type: "summary")
issuers_requested, issuers_audited, issuers_with_high_severity,
findings_by_rule, unreachable_issuers, issuers_changed_since_baseline,
grades, baseline_key, checks and note.
issuers_requested counts the issuers that you gave. issuers_audited counts
only the issuers that returned a metadata document that the rules could read, so
it always matches the number of issuer_audited events that the run charges.
The rest of the issuers are named in unreachable_issuers.
Risk grade
| Grade | Meaning |
|---|---|
F | Two or more high-severity findings. |
E | One high-severity finding. |
D | Three or more medium-severity findings. |
C | One or two medium-severity findings. |
B | Only low-severity findings. |
A | No finding. |
Changed since the last review
Give a baselineKey, for example q3-vendor-review. The Actor stores one small
snapshot for each issuer under that name, and it compares the next run against
it. The snapshot holds the endpoints, the declared methods, the key identifiers
and the rule identifiers that fired.
- On a first run there is nothing to compare against, so
changed_since_baselineisnull. That is normal and is not a defect. - On a later run
changed_since_baselineistrueorfalse, andbaseline_changesnames the fields that moved. - The name is only a record name in a key-value store. The run replaces every
character that is not a letter, a digit, a dot, a dash or an underscore with a
dash, and it keeps the first 60 characters.
Q3 vendor reviewtherefore becomesQ3-vendor-review. The summary row reports the name that the run used, so give the same name again at the next review.
Version 1 works with no stored state, because a single audit already gives you the review artefact.
A business verdict never fails the run
A failed gate, an unreachable vendor, a vendor without a valid discovery document and a run with no finding are all results of this product. Each one is a dataset row plus a run status message, and the run ends with SUCCEEDED. Only a real malfunction, such as an input that cannot be parsed, gives a FAILED run.
Pricing
The Actor uses the pay-per-event model. It charges these three events.
| Event | Unit | Price (USD) | When it is charged |
|---|---|---|---|
run_start | per run | 0.01 | Once for each run, after the input parses. |
issuer_audited | per issuer metadata set read and audited | 0.015 | Once for each issuer that returned a valid metadata document. An issuer that gave no valid document was not audited, so it is not charged. |
baseline_change_reported | per issuer that differs from its stored baseline | 0.01 | Only when you give a baselineKey and the issuer really moved. A first run and an unchanged issuer are not charged. |
The default maximum total charge for one run is 10 USD, which covers a vendor portfolio of about 600 issuers.
Limits
| Limit | Value |
|---|---|
| Issuers in one run | 1 to 200 |
| Requests for each issuer | about 6 to 10 small GET requests |
| Issuers read at one time | 5, so the Actor does not load the vendor |
| Request timeout | 5 to 60 s, default 15 s |
| Redirect hops for one fetch | 3, and each hop passes the public-target guard |
| Response body read | 512 KiB, and a larger body is not parsed |
| Baseline name | made safe, then cut to 60 letters, digits, dots, dashes or underscores |
Development
uv syncuv run pytestuv run ruff check .


