Trusted publishing
Trusted publishing lets you authorize an external CI/CD workload – usually a GitHub Actions run or GitLab CI/CD pipeline – to publish a specific content item without storing a long-lived Posit Connect API key as a pipeline secret.
Trusted publishing is enabled by default, but your administrator can disable it on the server.
Requirements
Before you begin:
- Trusted publishing must be enabled on the server. It is enabled by default, but an administrator can disable it.
- The content item must already exist in Connect. Trusted publishing authorizes an existing item; it does not create one.
- You must be the content’s owner or a collaborator who can change its settings.
- Your pipeline platform must be able to issue an OpenID Connect identity token (for example, GitHub Actions with
id-token: writepermission, or a GitLab CI/CD ID token).
Supported providers
A trusted publisher is described by a publisher type that tells Connect how the workload proves its identity. Supported providers include:
- GitHub Actions
- GitHub Enterprise Server
- GitLab CI/CD
- Custom OpenID Connect
GitHub Actions: immutable subject claims
GitHub repositories created on or after July 15, 2026, use immutable subject claims by default in their Actions OpenID Connect (OIDC) tokens. Older repositories can opt in to this format in the repository’s Settings > Actions > General page.
With immutable claims, the sub (subject) claim in the OIDC token embeds numeric IDs alongside human-readable names, delimited by @. For example, instead of:
repo:my-org/my-repo:ref:refs/heads/main
the token contains:
repo:my-org@123456/my-repo@789012:ref:refs/heads/main
When you configure a GitHub Actions trusted publisher in Connect, the subject claim values you enter must match the format your repository actually produces. If your repository uses immutable claims, enter the subject values with the @<id> suffixes included.
Finding your repository’s immutable identifiers
If you have the GitHub CLI installed and are authenticated, you can retrieve the identifiers for a repository:
# From within a local clone of the repository:
gh api "repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)" \
--jq '"\(.owner.login)@\(.owner.id)/\(.name)@\(.id)"'
# Or, for any repository by name:
gh api "repos/$ORG/$REPO" \
--jq '"\(.owner.login)@\(.owner.id)/\(.name)@\(.id)"'This prints the owner and repository in the immutable format (for example, my-org@123456/my-repo@789012). Use these values when filling in the trusted publisher fields in Connect.
Connect cannot resolve these identifiers for you because it does not hold credentials to the GitHub API.
Troubleshooting
If your trusted publisher configuration looks correct but publishing fails with an HTTP 400 error at the token-exchange step, the most likely cause is a mismatch between the subject claim format your repository produces and the values configured in Connect. Verify whether your repository uses immutable subject claims and update your publisher configuration accordingly.
Publish from your CI workflow
Once a publisher is authorized, your pipeline publishes in three steps:
- The pipeline obtains an OIDC identity token from its platform, requesting the audience you configured (
connectby default). - The pipeline exchanges that token at Connect’s OAuth token endpoint for a short-lived access token. Connect verifies the token against the provider and confirms it matches an authorized publisher.
- The pipeline uses the access token as its Connect credential to upload a bundle and deploy the content.
The access token is valid for about an hour and can only act on the content you authorized.
Posit maintains a dedicated GitHub Action that handles most of these steps for you. It can be used as follows:
.github/workflows/publish.yml
name: publish
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v6
- name: Deploy to Connect
uses: posit-dev/connect-actions/deploy@mainRemove a publisher
To revoke a publisher, open the content’s Access settings, find it in the Trusted Publishing list, and select the remove button next to it. The workload can no longer obtain an access token for this content once it is removed.