Workbench-managed Azure credentials

Enhanced Advanced

When Workbench is configured to use Microsoft Entra ID for Single Sign-On (SSO), it can grant users delegated permissions for Azure resources without requiring them to sign in again. These delegated credentials eliminate the need for end users to manage complex authentication workflows when accessing Azure services from within Workbench.

Azure delegated credentials support a range of use cases:

For information about configuring Azure delegated credentials as an administrator, see the Delegated Azure Credentials section of the Posit Workbench Administration Guide. The admin guide covers adding delegated permissions, granting consent, and exposing credentials to users.

Advantages

Using Azure delegated credentials through Workbench provides several key advantages:

  • No need to manage Azure service principals or client secrets yourself
  • Avoid hardcoding credentials in your code
  • Automatic token refresh handled by Workbench; see How token retrieval works for details
  • Securely access Azure resources using your existing Entra ID identity
  • Workbench derives credentials from your SSO login, so no additional sign-in required

How Azure credentials work in sessions

Unlike the advanced integrations (AWS, Databricks, Snowflake) which automatically set environment variables when you select them in the New Session dialog, Azure delegated credentials work differently:

  • Automatic availability: You can automatically access Azure credentials in all your sessions when your administrator has configured Workbench with Microsoft Entra ID SSO and the appropriate delegated permissions.
  • No session selection required: You do not need to enable Azure credentials in the New Session dialog. They are available by default.
  • On-demand tokens: You retrieve access tokens on demand by calling the Software Development Kit (SDK) functions described below. Each call specifies the Azure resource you want to access, and Workbench returns a token scoped to that resource.

Retrieving access tokens

Use the posit-sdk (Python) or rstudioapi (R) package to retrieve Azure access tokens. Each token is scoped to a specific Azure resource Uniform Resource Identifier (URI).

Installation

pip install posit-sdk

View Python SDK documentation

install.packages("rstudioapi")

View R SDK documentation

Getting an access token

To retrieve an access token, specify the resource URI for the Azure service you want to access. Common resource URIs include:

Azure Service Resource URI
Azure Storage https://storage.azure.com
Azure Key Vault https://vault.azure.net
Azure SQL Database https://database.windows.net
Azure Management https://management.azure.com
Microsoft Graph https://graph.microsoft.com
from posit.workbench import Client

client = Client()

# Get a token for Azure Storage
token = client.oauth.get_delegated_azure_token("https://storage.azure.com")

access_token = token["access_token"]
expires_in = token["expires_in"]  # seconds until expiry

print(f"Token expires in {expires_in} seconds")

# Use the token in API calls
import requests
headers = {"Authorization": f"Bearer {access_token}"}

View get_delegated_azure_token() documentation.

# Get a token for Azure Storage
token <- rstudioapi::getDelegatedAzureToken("https://storage.azure.com")

access_token <- token$access_token
expires_at <- token$expires_at  # Unix timestamp

cat("Token expires at:", format(as.POSIXct(expires_at, origin = "1970-01-01")), "\n")

View getDelegatedAzureToken() documentation or run ?rstudioapi::getDelegatedAzureToken in your Positron Pro / RStudio IDE R console.

ImportantToken security

Azure tokens are sensitive credentials. Never log, print, or store tokens in plain text. Use them only for authenticated API requests.

Azure DevOps Git integration

Important

Azure DevOps Git integration via git-credential-pwb is only supported in RStudio Pro sessions.

Workbench includes a Git credential helper (git-credential-pwb) that automatically provides Azure delegated credentials when you interact with Azure DevOps Git repositories. This means you can clone, pull, and push to Azure DevOps repos without configuring personal access tokens or other credentials.

Requirements

Your administrator must configure delegated permissions for Azure DevOps in the Workbench application registration in Entra ID. See the Delegated Azure Credentials section of the Posit Workbench Administration Guide for configuration instructions.

Cloning a repository

To clone an Azure DevOps repository, use the HTTPS clone URL from your Azure DevOps project:

git clone https://dev.azure.com/{organization}/{project}/_git/{repository}

For example:

git clone https://dev.azure.com/myorg/myproject/_git/myrepo

The git-credential-pwb helper automatically provides your Azure credentials to Git. No additional authentication steps are required.

How it works

Workbench configures the git-credential-pwb credential helper in your session’s Git configuration. When Git needs credentials for dev.azure.com, the helper requests a delegated Azure token scoped to the Azure DevOps application and returns it to Git.

NoteDebugging

If you encounter issues with Azure DevOps Git authentication, enable Git credential tracing to see what the credential helper is doing:

GIT_TRACE=1 git clone https://dev.azure.com/{organization}/{project}/_git/{repository}

Look for lines beginning with git-credential-pwb: trace: in the output for details about the credential resolution process.

Warning

Enabling GIT_TRACE may print access tokens and other sensitive credentials to your terminal output. Only use this for debugging, and clear your terminal history afterwards.

Example workflows

Azure Blob Storage

pip install posit-sdk azure-storage-blob
from posit.workbench import Client
from azure.core.credentials import AccessToken, TokenCredential
from azure.storage.blob import BlobServiceClient
import time


class WorkbenchAzureCredential(TokenCredential):
    """Wraps a Workbench delegated token for use with Azure SDK clients.

    This implementation refreshes the delegated token automatically when
    it is missing or close to expiry.
    """

    def __init__(self, client: Client, resource: str):
        self._client = client
        self._resource = resource
        self._token = None
        self._expires_on = 0

    def _refresh_token(self) -> None:
        token = self._client.oauth.get_delegated_azure_token(self._resource)
        self._token = token["access_token"]
        self._expires_on = int(time.time()) + token["expires_in"]

    def get_token(self, *scopes, **kwargs):
        # Refresh if we have no token yet or if it is close to expiry (within 60 seconds)
        now = int(time.time())
        if self._token is None or now >= self._expires_on - 60:
            self._refresh_token()
        return AccessToken(self._token, self._expires_on)


client = Client()
credential = WorkbenchAzureCredential(client, "https://storage.azure.com")

blob_service = BlobServiceClient(
    account_url="https://<storage_account>.blob.core.windows.net",
    credential=credential
)

# List containers
for container in blob_service.list_containers():
    print(container["name"])
library(AzureStor)

token <- rstudioapi::getDelegatedAzureToken("https://storage.azure.com")

# Connect to a storage endpoint
endpoint <- storage_endpoint(
  "https://<storage_account>.blob.core.windows.net",
  token = token$access_token
)

# List containers
list_storage_containers(endpoint)

Microsoft Graph API

pip install posit-sdk requests
from posit.workbench import Client
import requests

client = Client()
token = client.oauth.get_delegated_azure_token("https://graph.microsoft.com")

headers = {"Authorization": f"Bearer {token['access_token']}"}
response = requests.get("https://graph.microsoft.com/v1.0/me", headers=headers)
print(response.json())
library(httr2)

token <- rstudioapi::getDelegatedAzureToken("https://graph.microsoft.com")

response <- request("https://graph.microsoft.com/v1.0/me") |>
  req_auth_bearer_token(token$access_token) |>
  req_perform()

resp_body_json(response)

How token retrieval works

Each time you call get_delegated_azure_token() (posit-sdk) or getDelegatedAzureToken() (rstudioapi), Workbench exchanges the refresh token from your SSO login for a new access token scoped to the requested resource. This means:

  • Every call returns a fresh access token from Entra ID. The SDK itself does not cache or reuse tokens between calls.
  • You do not need to implement any refresh logic for the underlying SSO refresh token; Workbench manages that for you.
  • Repeatedly calling the token function in a tight loop will perform a token exchange on each call, which can add latency and load and may be subject to throttling by Entra ID.
  • Workbench manages the underlying refresh token, which it obtained when you signed in. If it expires (for example, after a long period of inactivity), you need to sign out of Workbench and sign back in.

Best practices

  • For occasional API calls, you can simply call the token function whenever you need a token and use the returned access token immediately.
  • For high-frequency API calls (for example, inside a tight loop), consider caching the access token in memory and reusing it until shortly before it expires, instead of calling the token function on every request. Do not write tokens to disk or other persistent storage.
  • Handle errors. If the token exchange fails (for example, the SSO refresh token has expired or permissions have been revoked), the Python SDK raises a RuntimeError (or an HTTPError for server-level failures) and the R SDK calls stop() with a descriptive message. When this happens, sign out of Workbench and sign back in.
  • Never log tokens. Avoid printing or logging Azure tokens in your code. Tokens should only be used for authenticated API requests.

Troubleshooting

If get_delegated_azure_token() (Python) or getDelegatedAzureToken() (R) returns an error:

  • Verify that your administrator has configured Azure delegated credentials. See the Delegated Azure Credentials admin guide.
  • Confirm that the resource URI is correct and that delegated permissions have been granted for that resource in Entra ID.
  • Check that your Workbench session was started after the administrator configured the permissions. You might need to sign out of Workbench and sign back in to pick up new permissions.

If Azure DevOps Git operations fail:

  • Ensure that delegated permissions for Azure DevOps have been configured in Entra ID.
  • Verify that you are using the HTTPS clone URL (not SSH).
  • Run GIT_TRACE=1 before the Git command to see debug output from git-credential-pwb.
  • Check that your Azure DevOps organization is in the same Entra ID tenant as Workbench.

If a token works, but API calls fail with 403 Forbidden:

  • Contact your administrator to verify the permissions configured in Entra ID. The delegated permissions might not include the specific scope required by the API you are calling.
  • Confirm that admin consent has been granted, since some Azure services require admin consent for delegated permissions.

For persistent issues, contact your administrator with the resource URI and any error messages.

Back to top