ARTIFACTORY: How to use OIDC with Cargo in GitHub Actions

ARTIFACTORY: How to use OIDC with Cargo in GitHub Actions

Products
Frog_Artifactory
Content Type
Integrations
AuthorFullName__c
Raphael Zaafrani
articleNumber
000006857
FirstPublishedDate
2026-02-03T10:25:54Z
lastModifiedDate
2026-02-03
Introduction 

At the time of writing this article, the JF CLI does not support Cargo. As such, setting up a Cargo project in GitHub Actions can prove challenging. In this guide, I will explain how to set up a GitHub Actions pipeline to utilize Artifactory's functionalities with Cargo while authenticating with OIDC. 


Adding The Registry:


First, you will want to set up the config.toml file to allow the Cargo client in the GitHub runner to reach your Artifactory instance:
   steps:
    - name: add registry
      run: |
           touch /home/runner/.cargo/config.toml
           echo "[registry]" >> /home/runner/.cargo/config.toml
           echo "default = \"artifactory\"" >> /home/runner/.cargo/config.toml
           echo "global-credential-providers = [\"cargo:token\"]" >> /home/runner/.cargo/config.toml
           echo "[registries.artifactory]" >> /home/runner/.cargo/config.toml
           echo "index = \"sparse+${{ secrets.ART_URL }}/artifactory/api/cargo/${{ vars.REPO }}/index/\"" >> /home/runner/.cargo/config.toml
           echo "[source.artifactory-remote]" >> /home/runner/.cargo/config.toml
           echo "registry = \"sparse+${{ secrets.ART_URL }}/artifactory/api/cargo/${{ vars.REPO }}/index/\"" >> /home/runner/.cargo/config.toml
           echo "[source.crates-io]"  >> /home/runner/.cargo/config.toml
           echo "replace-with = \"artifactory-remote\""  >> /home/runner/.cargo/config.toml

Here we create the config.toml file to be used by the client, let's dissect some important arguments used:
  • echo "default = \"artifactory\"" >> /home/runner/.cargo/config.toml Here we set Cargo's default registry to Artifactory. This is done to avoid having to use "--registry=artifactory" on every request.
  • echo "global-credential-providers = [\"cargo:token\"]" >> /home/runner/.cargo/config.toml Now we specify that we will use a token to authenticate. 
  • echo "index = \"sparse+${{ secrets.ART_URL }}/artifactory/api/cargo/${{ vars.REPO }}/index/\"" >> /home/runner/.cargo/config.toml Importantly, here we set the index and later the registry address. The secrets.ART_URL and vars.REPO variables are the first few we will need to set in our project, ART_URL being the URL for your instance in the form of "https://artifactory.com", and REPO being the name of the repository to be used for resolution. 
  • The rest keeps setting up the client in a similar fashion, so we'll move on.

Authentication:


Now we will need to set up authentication. In this guide, we will use the OIDC integration to fetch an access token. If you'd like to just use a static access token, you could use only the "add token" step, passing the access token as a secret instead of the environment variable.
   - name: Get id token
      run: |
          ID_TOKEN=$(curl -sLS -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
                    "${ACTIONS_ID_TOKEN_REQUEST_URL}" | jq .value | tr -d '"')
          echo "ID_TOKEN=${ID_TOKEN}" >> $GITHUB_ENV
    - name: Exchange token with access
      env:
          ID_TOKEN: ${{ env.ID_TOKEN }}
          JFROG_PLATFORM_URL: ${{ secrets.ART_URL }}
      run: |
          ACCESS_TOKEN=$(curl -XPOST -H "Content-Type: application/json" "${{ secrets.ART_URL }}/access/api/v1/oidc/token" -d "{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"${ID_TOKEN}\", \"provider_name\": \"${{ secrets.PROVIDER_NAME }}\"}" | jq .access_token | tr -d '"')
          echo "ACCESS_TOKEN=${ACCESS_TOKEN}" >> $GITHUB_ENV
          echo "::add-mask::$ACCESS_TOKEN"
    - name: add token
      run: |
           touch /home/runner/.cargo/credentials.toml
           echo "[registries.artifactory]" >> /home/runner/.cargo/credentials.toml
           echo " token=\"Bearer ${{ env.ACCESS_TOKEN }}\"" >> /home/runner/.cargo/credentials.toml
Now we're looking at setting up the credentials.toml file, here is the breakdown:
  • First, getting the ID token from the OIDC provider:
       - name: Get id token
          run: |
              ID_TOKEN=$(curl -sLS -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
                        "${ACTIONS_ID_TOKEN_REQUEST_URL}" | jq .value | tr -d '"')
              echo "ID_TOKEN=${ID_TOKEN}" >> $GITHUB_ENV

     Here, we request the ID token from GitHub and store it in the GitHub environment. 

  • This token is then sent to Artifactory to be exchanged for an Access Token:
     - name: Exchange token with access
          env:
              ID_TOKEN: ${{ env.ID_TOKEN }}
              JFROG_PLATFORM_URL: ${{ secrets.ART_URL }}
          run: |
              ACCESS_TOKEN=$(curl -XPOST -H "Content-Type: application/json" "${{ secrets.ART_URL }}/access/api/v1/oidc/token" -d "{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"${ID_TOKEN}\", \"provider_name\": \"${{ secrets.PROVIDER_NAME }}\"}" | jq .access_token | tr -d '"')
              echo "ACCESS_TOKEN=${ACCESS_TOKEN}" >> $GITHUB_ENV
              echo "::add-mask::$ACCESS_TOKEN"

     

    Now that we have the ID token from GitHub we can use it in a request to the /access/api/v1/oidc/token API endpoint to exchange it with an access token. To perform this request we use another previously declared secret "PROVIDER_NAME", this will be the name of the provider defined in Artifactory, more information about that here

    After storing the token in the GitHub environment we run "echo "::add-mask::$ACCESS_TOKEN"" to hide the content of the token in the console. 

  • Finally, we add the newly created token to the credentials.toml file to be used by the Cargo client:
     - name: add token
          run: |
               touch /home/runner/.cargo/credentials.toml
               echo "[registries.artifactory]" >> /home/runner/.cargo/credentials.toml
               echo " token=\"Bearer ${{ env.ACCESS_TOKEN }}\"" >> /home/runner/.cargo/credentials.toml

       Once this is done we're all set to use our Artifactory instance as a Cargo registry. 

Putting it together:


Having it all together an example Workflow file would look like this:
name: Rust Exemple

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

env:
  CARGO_TERM_COLOR: always
      
jobs:
  build:
    permissions:
      contents: read
      id-token: write
    runs-on: ubuntu-latest

    steps:
    - name: add registry
      run: |
           touch /home/runner/.cargo/config.toml
           echo "[registry]" >> /home/runner/.cargo/config.toml
           echo "default = \"artifactory\"" >> /home/runner/.cargo/config.toml
           echo "global-credential-providers = [\"cargo:token\"]" >> /home/runner/.cargo/config.toml
           echo "[registries.artifactory]" >> /home/runner/.cargo/config.toml
           echo "index = \"sparse+${{ secrets.ART_URL }}/artifactory/api/cargo/${{ vars.REPO }}/index/\"" >> /home/runner/.cargo/config.toml
           echo "[source.artifactory-remote]" >> /home/runner/.cargo/config.toml
           echo "registry = \"sparse+${{ secrets.ART_URL }}/artifactory/api/cargo/${{ vars.REPO }}/index/\"" >> /home/runner/.cargo/config.toml
           echo "[source.crates-io]"  >> /home/runner/.cargo/config.toml
           echo "replace-with = \"artifactory-remote\""  >> /home/runner/.cargo/config.toml
    - name: Get id token
      run: |
          ID_TOKEN=$(curl -sLS -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
                    "${ACTIONS_ID_TOKEN_REQUEST_URL}" | jq .value | tr -d '"')
          echo "ID_TOKEN=${ID_TOKEN}" >> $GITHUB_ENV
    - name: Exchange token with access
      env:
          ID_TOKEN: ${{ env.ID_TOKEN }}
          JFROG_PLATFORM_URL: ${{ secrets.ART_URL }}
      run: |
          ACCESS_TOKEN=$(curl -XPOST -H "Content-Type: application/json" "${{ secrets.ART_URL }}/access/api/v1/oidc/token" -d "{\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\", \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", \"subject_token\": \"${ID_TOKEN}\", \"provider_name\": \"${{ secrets.PROVIDER_NAME }}\"}" | jq .access_token | tr -d '"')
          echo "ACCESS_TOKEN=${ACCESS_TOKEN}" >> $GITHUB_ENV
          echo "::add-mask::$ACCESS_TOKEN"
    - name: add token
      run: |
           touch /home/runner/.cargo/credentials.toml
           echo "[registries.artifactory]" >> /home/runner/.cargo/credentials.toml
           echo " token=\"Bearer ${{ env.ACCESS_TOKEN }}\"" >> /home/runner/.cargo/credentials.toml
    
    - name: Build
      run: cargo install helloworld --verbose

Now you are ready to use Artifactory in your Rust GitHub Actions Pipelines, just replace the "Build" step and use Cargo as you usually would.