GitHub

Providers

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

ProviderTrustsDocs
VercelDeployments from a team or projectVercel
GitHub ActionsWorkflows from a repositoryGitHub
GitLab CIJobs from a project pipelineGitLab
GoogleA service accountGoogle
BitbucketA workspace's pipelinesBitbucket
AWS EKSA cluster service accountAWS EKS
AzureAn Entra ID workloadAzure
Custom OIDCAny OIDC issuerCustom

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

ItemRole
coreComposed policy form for the default GitHub + Vercel starter
policyOidcPolicy type, validation, and match/explain helpers
verifyServer-side token verification against policy rules
page-actionsExample settings page and savePolicy server action
claimsAdditional-claims editor and claim helpers
pickerMulti-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:

  1. Fields. Add the property. If you installed Zod or Valibot, add it to schema instead. The type is inferred.
  2. DEFAULTS. Give the new field an empty default.
  3. compile and parse. Write the claim, and read it back when a saved policy loads. Add the claim name to FIRST_CLASS_CLAIMS so additional-claim rows cannot reuse it.
  4. The form. Render the input. Copy the field above it.
components/oidc/provider-google.tsx
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.