Identity providers you can install, the fields each form collects, and how to extend a form after install.
Each provider is a form your users fill in. Submit emits an OidcPolicy. Pick providers in the builder, or add them with the CLI.
Included providers
| Provider | Trusts | Docs |
|---|---|---|
| Vercel | Deployments from a team or project | Vercel |
| GitHub Actions | Workflows from a repository | GitHub |
| GitLab CI | Jobs from a project pipeline | GitLab |
| A service account | ||
| Bitbucket | A workspace's pipelines | Bitbucket |
| AWS EKS | A cluster service account | AWS EKS |
| Azure | An Entra ID workload | Azure |
| Custom OIDC | Any OIDC issuer | Custom |
Item names add optional -<form> and -<validation> suffixes (rhf, tanstack, zod, valibot). Example: GitHub with React Hook Form and Zod is @oidc/provider-github-rhf-zod.
npx shadcn@latest list @oidc is the source of truth for the full set.
Shared items
| Item | Role |
|---|---|
core | Composed policy form for the default GitHub + Vercel starter |
policy | OidcPolicy type, validation, and match/explain helpers |
verify | Server-side token verification against policy rules |
page-actions | Example settings page and savePolicy server action |
claims | Additional-claims editor and claim helpers |
picker | Multi-provider toggle used when more than one provider is selected |
See Save and verify for policy, verify, and page-actions.
Additional claims
Every form ends with an Additional claims list. Use it for claims the form has no dedicated field for.
- Names: letters, digits, dots, dashes, underscores.
- Values: comma-separated. A value that itself contains a comma cannot round-trip.
- A name that already has a dedicated field is rejected.
If you need its own label and validation, add a field to the installed file.
Add a field
After install, the form is yours. It lives at components/oidc/provider-<name>.tsx. Edit that file.
For a one-off claim, use Additional claims. For its own input, update four places in the same file:
Fields. Add the property. If you installed Zod or Valibot, add it toschemainstead. The type is inferred.DEFAULTS. Give the new field an empty default.compileandparse. Write the claim, and read it back when a saved policy loads. Add the claim name toFIRST_CLASS_CLAIMSso additional-claim rows cannot reuse it.- The form. Render the input. Copy the field above it.
const FIRST_CLASS_CLAIMS = ["aud", "email", "sub", "hd"]
type Fields = {
email: string
uniqueId: string
audience: string
hostedDomain: string
extraClaims: ClaimRow[]
}
function compile(fields: Fields) {
const claims: Record<string, string[]> = {}
// ...existing claims
if (fields.hostedDomain) {
claims.hd = [fields.hostedDomain]
}
mergeClaimRows(claims, fields.extraClaims, FIRST_CLASS_CLAIMS)
return { issuer: ISSUER, claims }
}With Zod, add the field to schema instead of Fields:
const schema = z.object({
email: emailSchema,
uniqueId: uniqueIdSchema,
audience: audienceSchema,
hostedDomain: z.string(),
extraClaims: extraClaimsSchema,
})parse must return null when the saved policy has a shape the form cannot represent, for example a multi-value first-class claim. Each provider page lists the claims that already have dedicated fields.