docs: add OIDC connections troubleshooting and clarify rulesets (#26276)

adding troubleshooting, failure UI, examples for rulesets

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alexa KristensenandCursor authored and GitHub committed 2026-10-12 13:06:02 -05:00
1 parent 547efd2d03
commit db384a4bd8
4 files changed
+321 -58

No files matched your search

@@ -20,7 +20,7 @@ vendor that can grant fine-grained access to your Docker resources.
OIDC connections follow the OpenID Connect (OIDC) standard. Establishing a
trust relationship involves creating the connection, configuring a
workflow, and testing. For example, a trust relationship between Docker and
workflow, and testing. A connection, then, is the named trust relationship in Docker Home that workflows point to. For example, a trust relationship between Docker and
GitHub follows these steps:
- GitHub issues a JWT ID token for the workflow run.
@@ -41,3 +41,4 @@ For how OIDC connections compare to organization access tokens, see
- [Create an OIDC connection](/manuals/security/authentication/oidc-connections/create-manage.md)
- [OIDC rulesets and subject claims](/manuals/security/authentication/oidc-connections/rulesets-claims.md)
- [Troubleshoot OIDC connections](/manuals/security/authentication/oidc-connections/troubleshoot.md)
@@ -1,6 +1,6 @@
---
title: Create and manage OIDC connections
linkTitle: Create and manage connections
linkTitle: Create and manage
description: Create and manage OIDC connections in Docker Home, then authenticate GitHub Actions to Docker Hub with docker/login-action and short-lived tokens
keywords: oidc connections, create oidc connection, github actions, docker/login-action, DOCKERHUB_OIDC_CONNECTIONID, openid connect, docker hub, enterprise security, admin
tags: [admin]
@@ -26,8 +26,9 @@ with a short-lived token.
1. Sign in to [Docker Home](https://app.docker.com/), select your
organization, then go to **Identity & auth**.
1. Select **OIDC connections**.
1. Select **Create OIDC connection** and fill in the OIDC connection form.
- Provide rulesets and subject claims. Other values are optional.
1. Select **Create OIDC connection** and fill in the form.
- **Connection name**, a **Ruleset name**, and a **Subject claim** are
required. **Description** is optional.
- For rulesets, subject claims, and resources, see
[OIDC connections rulesets and subject claims](/manuals/security/authentication/oidc-connections/rulesets-claims.md).
1. Select **Create connection**.
@@ -73,7 +74,8 @@ connections** page.
1. Find the row with your target connection ID.
1. Select the action menu icon for your options.
- **Edit** opens the **Edit OIDC connection** page where you can copy
your connection ID, update rulesets, or view the **Failures** table.
your connection ID, update rulesets, or open the **Failures** tab.
See [View connection failures](#view-connection-failures).
- **Deactivate** temporarily disables access to your GitHub workflow.
- **Activate** restores access to your GitHub workflow.
- **Delete** permanently deletes a connection.
@@ -92,6 +94,51 @@ fails at the token-exchange step until you activate the connection.
> replacement connection ID in every affected workflow before it runs
> again.
## View connection failures
Docker records a failure when a workflow reaches the token-exchange step
for your connection and no ruleset matches the token's claims. For GitHub
Actions, Docker only logs the failure when the token's repository
namespace matches a namespace in a `sub` rule on the connection. An
unrelated repository can still receive `access denied` without a
**Failures** row.
1. Sign in to [Docker Home](https://app.docker.com/), select your
organization, then go to **Identity & auth**.
1. Select **OIDC connections**.
1. Find the connection, open the action menu, and select **Edit**.
1. On the **Edit OIDC connection** page, select the **Failures** tab.
The **Failures** tab is view-only. It lists past failed exchanges so you
can compare claims to rulesets. It does not run a test or accept inputs.
If Docker has not recorded any failures for the connection, the tab shows
**No failures have been reported for this connection**.
> [!NOTE]
> Wrong connection IDs, deactivated connections, and token problems that
> fail before claim matching do not appear on **Failures**. See
> [Troubleshoot OIDC connections](/manuals/security/authentication/oidc-connections/troubleshoot.md).
### Read a failure entry
Each failure row includes:
- The date and time of the failed exchange
- The ruleset rule that did not match, shown as `claim = expected value`
(for example, `sub = repo:my-org/my-repo:ref:refs/heads/main`)
- The incoming claim value from the GitHub ID token, marked with ❌ when
it does not match
To inspect every claim in the token, expand **Show all claims**. The
expanded table lists **Incoming claim** and **Value**. Claims that failed
validation appear with ❌.
Use the unmatched expected value and the incoming value together to
decide whether to update the ruleset or the workflow that produced the
token.
## Next steps
- [OIDC connections rulesets and subject claims](/manuals/security/authentication/oidc-connections/rulesets-claims.md)
- [Troubleshoot OIDC connections](/manuals/security/authentication/oidc-connections/troubleshoot.md)
@@ -1,72 +1,62 @@
---
title: OIDC connections rulesets and subject claims
title: Configure OIDC rulesets and subject claims
linkTitle: Rulesets and subject claims
description: Configure rulesets and subject claims to control OIDC workflow access
keywords: oidc connections, rulesets, subject claims, github actions, jwt claims, access control, wildcards, enterprise security
description: >-
Rulesets and subject claims control which GitHub Actions workflows can
push images, pull images, read public repositories, and connect to Docker
Build Cloud.
keywords: >-
oidc connections, rulesets, subject claims, github actions, openid connect,
image push, image pull, docker build cloud, wildcards, access control
tags: [admin]
weight: 20
toc_max: 2
aliases:
- /enterprise/security/oidc-connections/rulesets-claims/
---
{{< summary-bar feature_name="OIDC connections" >}}
Rulesets and subject claims define what actions your GitHub workflows can
take with your Docker resources. Use them to authorize GitHub workflow
behaviors for an OIDC connection.
Rulesets and subject claims authorize which GitHub workflows can use which
Docker resources on an OIDC connection.
## Rulesets
A ruleset is a set of conditions that Docker evaluates against an incoming
GitHub ID token. When a workflow triggers an OIDC exchange, Docker checks
the token against every ruleset defined in your connection. If a ruleset's
conditions are satisfied, Docker grants access based on the parameters set
by that ruleset.
When a workflow triggers an OIDC exchange, Docker checks the token's
subject claim against every ruleset on the connection. If the subject
claim matches, Docker grants the resources and scopes on that ruleset.
Each ruleset contains the following fields:
Each ruleset has these fields:
- Label: A name for the ruleset.
- Rules: One or more conditions based on OIDC token claims, such as the
repository name, branch, or workflow path.
- These are expressed as subject claim strings.
- See [Subject claims](#subject-claims).
- Resources: The Docker resources a workflow can access when the ruleset
matches. See [Resources](#resources).
- Scopes: The permissions granted on those resources, such as read or write
access.
- **Ruleset name**: A name for the ruleset.
- **Subject claim**: One `sub` string from the GitHub ID token.
- **Resources**: What the workflow can access.
- **Scopes**: The access granted on those resources.
You can define between 1 and 5 rulesets per connection. Use multiple
rulesets to apply different access levels across different workflows or
branches. If more than one ruleset matches an incoming token, Docker merges
the resources from all matching rulesets and grants access to the combined
set.
You can add one to five rulesets on a connection. If more than one
ruleset matches a token, Docker grants the union of their resources and
scopes.
## Subject claims
A subject claim is the `sub` field in a GitHub-issued JWT ID token. It
encodes details of a workflow into a single string, identifying the
workflow by organization, repository, branch, environment, and so on.
encodes the workflow's organization, repository, branch, environment, and
related details into a single string. The repository, branch, tag, pull
request, or environment is part of that string, not a separate field.
Docker uses the subject claim as the primary condition when evaluating your
ruleset rules. The default subject claim format is:
The default format is:
```text
repo:<org>/<repo>:ref:refs/heads/<branch>
```
For example:
You can use wildcards to match across repositories or branches:
```text
repo:octo-org/octo-repo:ref:refs/heads/main
```
The exact format varies and depends on what triggered the workflow.
- A branch push, pull request, tag, or environment deployment each produces
a different `sub` value.
- Refer to
[GitHub's OpenID Connect reference](https://docs.github.com/en/actions/reference/security/oidc)
for the full list of formats.
| Pattern | Matches |
| :--------------------------------------------- | :--------------------------------------------------- |
| `repo:my-org/my-repo:ref:refs/heads/main` | Only the `main` branch of a specific repository |
| `repo:my-org/*` | All repositories in the organization |
| `repo:my-org/my-repo:ref:refs/heads/release-*` | All branches starting with `release-` |
> [!NOTE]
> GitHub repositories created after July 15, 2026 use immutable
@@ -75,23 +65,81 @@ The exact format varies and depends on what triggered the workflow.
> [GitHub changelog](https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/)
> for more details.
You can use wildcards to match across repositories or branches:
| Pattern | Matches |
| :--------------------------------------------- | :---------------------------------------------- |
| `repo:my-org/my-repo:ref:refs/heads/main` | Only the `main` branch of a specific repository |
| `repo:my-org/*` | All repos in the organization |
| `repo:my-org/my-repo:ref:refs/heads/release-*` | All branches starting with `release-` |
For the full list of formats, see
[GitHub's OpenID Connect reference](https://docs.github.com/en/actions/reference/security/oidc).
## Resources
Resources define the Docker resources a workflow can access when a ruleset
matches. You specify resources per ruleset, alongside the scopes that
determine the level of access granted.
A resource is a Docker Hub repository or Docker Build Cloud builder.
Scopes on the matching ruleset decide what the workflow can do with a defined resource.
Docker Hub repositories and Docker Build Cloud are supported resources.
- A repository resource is a Docker Hub repository in your organization.
**Image Pull** and **Image Push** apply to that repository. **Read
public repositories** applies to public repositories.
- A Docker Build Cloud resource uses the **Cloud Connect** scope, so the
workflow can connect and build in Docker Build Cloud.
## Ruleset examples
The following examples are working setups you can adapt. They are not
exhaustive, and they are not the only valid way to configure a
connection. Use them when you decide how to allocate your five
rulesets.
Start with one ruleset. Add more when different branches or permissions
need to change independently. Each example is a complete setup on its
own.
### Publish from main and use Build Cloud
Use one ruleset when the same workflows need several permissions and
you want to change those permissions together.
| Ruleset name | Subject claim | Resources and scopes |
| :----------- | :-------------------------------------------- | :------------------------------------------------------------------------------------------------- |
| `main` | `repo:octo-org/octo-repo:ref:refs/heads/main` | Repository `octo-org/octo-repo` with **Image Push**, and Docker Build Cloud with **Cloud Connect** |
Other branches receive `access denied` unless you add another ruleset.
### Different access for release branches and main
Split into two rulesets when release work should only pull an image,
but `main` should publish it. You can then tighten release access
without editing the publish rule.
| Ruleset name | Subject claim | Resources and scopes |
| :------------- | :------------------------------------------------- | :-------------------------------------------------- |
| `release-pull` | `repo:octo-org/octo-repo:ref:refs/heads/release-*` | Repository `octo-org/octo-repo` with **Image Pull** |
| `main-push` | `repo:octo-org/octo-repo:ref:refs/heads/main` | Repository `octo-org/octo-repo` with **Image Push** |
With this setup:
- Branches whose names start with `release-` can pull the image.
- Workflows on `main` can publish the image.
- Other branches, such as `feature-x`, receive `access denied`.
### Combine a broad read rule with a narrow push rule
Use two overlapping rulesets when every repository in the GitHub org
should read public images, but only `main` in one repository should
publish.
| Ruleset name | Subject claim | Resources and scopes |
| :----------- | :-------------------------------------------- | :----------------------------------------------------- |
| `main-push` | `repo:octo-org/octo-repo:ref:refs/heads/main` | Repository `octo-org/octo-repo` with **Image Push** |
| `org-read` | `repo:octo-org/*` | Public repositories with **Read public repositories** |
With this setup:
- A workflow on `main` matches both rulesets, so it can publish the
image and read public repositories.
- A workflow on any other branch or repository in `octo-org` matches
`org-read` only, so it can read public repositories.
- Deleting `org-read` removes the shared read permission and leaves the
publish rule unchanged.
## Next steps
- [OIDC connections overview](/manuals/security/authentication/oidc-connections/_index.md)
- [Create or manage OIDC connections](/manuals/security/authentication/oidc-connections/create-manage.md)
- [Troubleshoot OIDC connections](/manuals/security/authentication/oidc-connections/troubleshoot.md)
@@ -0,0 +1,167 @@
---
title: Troubleshoot OIDC connections
linkTitle: Troubleshoot
description: >-
Troubleshoot common OIDC connection token-exchange errors with GitHub
Actions
weight: 30
keywords: >-
oidc troubleshooting, oidc connection errors, Failures tab, github actions
oidc, subject claims, rulesets, docker login-action,
DOCKERHUB_OIDC_CONNECTIONID, access denied, connection_id is invalid,
subject_token
tags: [Troubleshooting, admin]
toc_max: 2
---
{{< summary-bar feature_name="OIDC connections" >}}
OIDC connection problems can stem from mismatched rulesets, an inactive
or incorrect connection ID, or your GitHub Actions workflow. The following
sections describe common errors and how to resolve them.
To inspect failed token exchanges in Docker Home, see
[View connection failures](/manuals/security/authentication/oidc-connections/create-manage.md#view-connection-failures).
## Subject claim does not match a ruleset
### Error message
In GitHub Actions, the login step fails during token exchange. Docker
returns:
```text
access denied
```
When Docker records the failure, the **Failures** tab shows the expected
subject claim next to the incoming `sub` value from GitHub. If there is
no failure row, confirm the workflow uses the correct connection ID and
that a ruleset `sub` pattern covers that repository's namespace. See
[View connection failures](/manuals/security/authentication/oidc-connections/create-manage.md#view-connection-failures).
### Causes
- The workflow's repository, branch, tag, pull request, or environment
produces a different `sub` value than the ruleset expects.
- The ruleset uses a narrow pattern and the workflow runs from a
different ref (for example, a feature branch instead of `main`).
- The ruleset still uses a mutable `repo:org/repo:...` subject while the
GitHub repository issues an immutable subject claim. See
[Subject claims](/manuals/security/authentication/oidc-connections/rulesets-claims.md#subject-claims).
### Solutions
1. Open the connection's **Failures** tab, if a row exists, and compare
the expected `sub` value with the incoming value marked ❌.
1. Update the ruleset's **Subject claim** on the **Rulesets** tab so it
matches the workflow, or use a wildcard where appropriate. See
[Rulesets and subject claims](/manuals/security/authentication/oidc-connections/rulesets-claims.md).
1. Select **Save connection**, then re-run the GitHub Actions workflow.
## Connection ID is invalid or the connection is inactive
### Error message
In GitHub Actions, the login step fails during token exchange. Docker
returns:
```text
connection_id is invalid
```
If the workflow omits the connection ID entirely, Docker returns
`connection_id is required when subject_token_type is id_token`
instead.
`connection_id is invalid` also appears when the ID is malformed, does
not exist, or the connection is deactivated or deleted. Deactivated and
deleted connections are not available for token exchange, so Docker
treats the ID as invalid.
This failure does not add a row on the **Failures** tab.
### Causes
- `DOCKERHUB_OIDC_CONNECTIONID` is missing from the workflow, or its
value does not match the connection ID shown in Docker Home.
- The connection was deactivated from the **OIDC connections** action
menu. Inactive connections use the same invalid-ID error as unknown
IDs.
- The connection was deleted and the workflow still references the old
ID.
### Solutions
1. In Docker Home, open **OIDC connections** and confirm the connection
status.
1. If the connection is inactive, open the action menu and select
**Activate**.
1. If the connection was deleted, create a new connection and update
`DOCKERHUB_OIDC_CONNECTIONID` in every affected workflow. See
[Create and manage OIDC connections](/manuals/security/authentication/oidc-connections/create-manage.md).
1. If the connection is active, copy the connection ID from the **Edit
OIDC connection** page and confirm the workflow uses that exact
value.
## Subject token errors
### Error message
In GitHub Actions, the login step fails before or during token exchange.
Docker may return one of:
```text
subject_token is required
subject_token is invalid
subject_token has expired
subject_token audience mismatch
subject_token issuer mismatch
```
These failures do not appear on the **Failures** tab because the
exchange fails before Docker evaluates your rulesets.
### Causes
- The workflow does not supply a GitHub OIDC ID token to the login step.
- The token expired, is not yet valid, or does not match the expected
issuer or audience.
- The token cannot be verified against the provider's keys.
### Solutions
1. Confirm the job grants GitHub permission to issue an OIDC token:
```yaml
permissions:
contents: read
id-token: write
```
1. Use `docker/login-action` version 4.5.0 or later with your
organization name and connection ID. See
[Configure a GitHub Actions workflow](/manuals/security/authentication/oidc-connections/create-manage.md#configure-a-github-actions-workflow).
1. Re-run the workflow so GitHub issues a fresh ID token.
## Username is not an organization
### Causes
- The `username` input to `docker/login-action` is a personal Docker Hub
account instead of an organization name.
- Only organization accounts can sign in with OIDC connections.
### Solutions
1. Set `username` to the Docker organization that owns the OIDC
connection.
1. Confirm that organization matches the one where you created the
connection in Docker Home.
## Related information
- [Create and manage OIDC connections](/manuals/security/authentication/oidc-connections/create-manage.md)
- [View connection failures](/manuals/security/authentication/oidc-connections/create-manage.md#view-connection-failures)
- [OIDC rulesets and subject claims](/manuals/security/authentication/oidc-connections/rulesets-claims.md)
- [OIDC connections overview](/manuals/security/authentication/oidc-connections/_index.md)