Skip to content

[Auth] Keyless CI/CD auth via OIDC token exchange#4326

Merged
hanouticelina merged 10 commits into
mainfrom
oidc-trusted-publishers
Jun 10, 2026
Merged

[Auth] Keyless CI/CD auth via OIDC token exchange#4326
hanouticelina merged 10 commits into
mainfrom
oidc-trusted-publishers

Conversation

@hanouticelina

@hanouticelina hanouticelina commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

This PR lets CI jobs authenticate to the Hub without storing an HF_TOKEN secret, using the Hub's Trusted Publishers. Set HF_OIDC_RESOURCE to the repo (or username) to scope a short-lived token to, and huggingface_hub does the OIDC exchange under the hood, no token, no setup code.

Example: publish a model and a dataset from one training run

name: Publish to the Hub

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write    # required so the job can mint an OIDC token
      contents: read
    steps:
      - uses: actions/checkout@v4

      - name: Install the hf CLI
        run: |
          curl -LsSf https://hf.co/cli/install.sh | bash
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

      - name: Train
        run: ./train.sh    # produces ./model and ./dataset

      # Scope `HF_OIDC_RESOURCE` per step to the repo that step pushes to.
      - name: Push the model
        env:
          HF_OIDC_RESOURCE: acme/awesome-model
        run: hf upload acme/awesome-model ./model .

      - name: Push the dataset
        env:
          HF_OIDC_RESOURCE: datasets/acme/awesome-dataset
        run: hf upload acme/awesome-dataset ./dataset . --repo-type dataset

Under the hood, get_token() gains a last-resort source: when HF_OIDC_RESOURCE is set and a supported CI provider is detected, it mints the provider's OIDC id token, exchanges it at POST /oauth/token for a short-lived Hub token, and caches it.


Note

High Risk
Changes core authentication in get_token() and introduces token exchange; misconfiguration or exchange failures affect all Hub calls when HF_OIDC_RESOURCE is set.

Overview
Adds Trusted Publishers keyless CI auth: CI jobs can authenticate to the Hub via OIDC token exchange instead of storing HF_TOKEN.

A new internal _oidc module mints GitHub Actions OIDC id tokens (when permissions: id-token: write is set) and exchanges them at POST /oauth/token (RFC 8693), scoped with resource. Other providers can pass a pre-minted id token via HF_OIDC_ID_TOKEN.

get_token() now tries OIDC last when HF_OIDC_RESOURCE is set (repo or username to scope the token). Failures raise OIDCError instead of silently returning unauthenticated. Exchanged tokens are cached with refresh before expiry for auto-minted GitHub flows.

Debug HF_DEBUG curl logging redacts OAuth body fields such as subject_token.

Reviewed by Cursor Bugbot for commit a48753a. Configure here.

@bot-ci-comment

bot-ci-comment Bot commented Jun 8, 2026

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@coyotte508 coyotte508 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment thread src/huggingface_hub/_oidc.py Outdated
Comment on lines +48 to +53
def detect_provider() -> str | None:
"""Detect the CI provider able to mint an OIDC id token, or `None` if not in a supported CI."""
if os.environ.get("GITHUB_ACTIONS") == "true":
return GITHUB
return None

@coyotte508 coyotte508 Jun 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a way to pass the ID token directly for other providers than Github

eg HF_OIDC_ID_TOKEN=... HF_OIDC_RESOURCE=... hf upload ...

so the Gitlab example can also be simplified!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in addition of HF_OIDC_ID_TOKEN we could also support Gitlab, etc. natively (can be a follow-up PR)

Comment thread src/huggingface_hub/utils/_auth.py
@hanouticelina hanouticelina marked this pull request as ready for review June 10, 2026 10:01

@Wauplin Wauplin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I left some cosmetic changes but otherwise looks good to me.

Could you also update the PR description with a more up-to-date example? e.g. install hf CLI using installer. Also potentially could be a more complex example pushing to both a dataset and a model at the end of a training step => would need to set HF_OIDC_RESOURCE per step targeting different resources. (asking because example will likely be copied to release notes)

Once merged the follow-up would be:

  • update hub-docs
  • add support/examples for more providers

Comment thread src/huggingface_hub/utils/_auth.py Outdated
Comment thread src/huggingface_hub/utils/_auth.py Outdated
Comment thread src/huggingface_hub/utils/_auth.py Outdated
Comment thread src/huggingface_hub/utils/_http.py Outdated
Comment thread src/huggingface_hub/utils/_http.py Outdated
Comment thread src/huggingface_hub/_oidc.py Outdated
Comment thread src/huggingface_hub/errors.py
@Wauplin Wauplin added the highlight PR will be highlighted in the release notes. label Jun 10, 2026

@Wauplin Wauplin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment thread src/huggingface_hub/cli/_errors.py Outdated
Co-authored-by: Lucain <lucain@huggingface.co>
@hanouticelina

Copy link
Copy Markdown
Collaborator Author

@Wauplin updated the PR description with a better example ✔️

@hanouticelina

Copy link
Copy Markdown
Collaborator Author

I'm talking care of the follow-up PRs as well

@hanouticelina hanouticelina merged commit e3b6d5b into main Jun 10, 2026
23 of 25 checks passed
@hanouticelina hanouticelina deleted the oidc-trusted-publishers branch June 10, 2026 13:26

@julien-c julien-c left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very elegantly implemented! kudos

@huggingface-hub-bot

Copy link
Copy Markdown
Contributor

This PR has been shipped as part of the v1.19.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

highlight PR will be highlighted in the release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants