Repository: prometheus/prometheus
File: storage/remote/azuread/azuread.go (Go)

Code before:
		clientID := azidentity.ClientID(managedIdentityConfig.ClientID)
		opts = &azidentity.ManagedIdentityCredentialOptions{ClientOptions: *clientOpts, ID: clientID}
	} else {
		opts = &azidentity.ManagedIdentityCredentialOptions{ClientOptions: *clientOpts}
	}
	return azidentity.NewManagedIdentityCredential(opts)
}

// newWorkloadIdentityTokenCredential returns new Microsoft Entra Workload Identity token credential.
// This is used for Kubernetes Pods that have been configured with the azure.workload.identity/use: "true" label
// and a service account annotated with azure.workload.identity/client-id annotation.
//
// For this to work properly, the Kubernetes pod must:
// 1. Have the label azure.workload.identity/use: "true"
// 2. Use a service account with annotation azure.workload.identity/client-id matching the ClientID
// 3. Have the Azure Workload Identity webhook installed in the cluster
// 4. Have federated identity credentials established between the identity and service account
//
// The token file path (typically DefaultWorkloadIdentityTokenPath) is mounted automatically
// by the Azure Workload Identity webhook when it mutates the pod. The webhook:
// - Projects the service account token to this path
// - Sets environment variables like AZURE_AUTHORITY_HOST and AZURE_FEDERATED_TOKEN_FILE
// - Adds the necessary volume mounts to the pod
//
// For detailed setup instructions, see:
// https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/prometheus-metrics-enable-workload-identity
func newWorkloadIdentityTokenCredential(clientOpts *azcore.ClientOptions, workloadIdentityConfig *WorkloadIdentityConfig) (azcore.TokenCredential, error) {
	opts := &azidentity.WorkloadIdentityCredentialOptions{
		ClientOptions: *clientOpts,
		ClientID:      workloadIdentityConfig.ClientID,
		TenantID:      workloadIdentityConfig.TenantID,
		TokenFilePath: workloadIdentityConfig.TokenFilePath,
	}

	return azidentity.NewWorkloadIdentityCredential(opts)
}

// newOAuthTokenCredential returns new OAuth token credential.
func newOAuthTokenCredential(clientOpts *azcore.ClientOptions, oAuthConfig *OAuthConfig) (azcore.TokenCredential, error) {
	opts := &azidentity.ClientSecretCredentialOptions{ClientOptions: *clientOpts}
	return azidentity.NewClientSecretCredential(oAuthConfig.TenantID, oAuthConfig.ClientID, oAuthConfig.ClientSecret, opts)
}

// newSDKTokenCredential returns new SDK token credential.
func newSDKTokenCredential(clientOpts *azcore.ClientOptions, sdkConfig *SDKConfig) (azcore.TokenCredential, error) {
	opts := &azidentity.DefaultAzureCredentialOptions{ClientOptions: *clientOpts, TenantID: sdkConfig.TenantID}
	return azidentity.NewDefaultAzureCredential(opts)
}

// newTokenProvider helps to fetch accessToken for different types of credential. This also takes care of
// refreshing the accessToken before expiry. This accessToken is attached to the Authorization header while making requests.

Review comment (bug):
Again, let's link to instructions instead? It's unlikely users will dive so deeply, to unexported function to debug the AzureWorkloadIdentity, especially if this comments gets stale.

```suggestion
//
// For detailed setup instructions, see:
// https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/prometheus-metrics-enable-workload-identity
```

Code after:
func newOAuthTokenCredential(clientOpts *azcore.ClientOptions, oAuthConfig *OAuthConfig) (azcore.TokenCredential, error) {
	opts := &azidentity.ClientSecretCredentialOptions{ClientOptions: *clientOpts}
	return azidentity.NewClientSecretCredential(oAuthConfig.TenantID, oAuthConfig.ClientID, oAuthConfig.ClientSecret, opts)
}

// newSDKTokenCredential returns new SDK token credential.
func newSDKTokenCredential(clientOpts *azcore.ClientOptions, sdkConfig *SDKConfig) (azcore.TokenCredential, error) {
	opts := &azidentity.DefaultAzureCredentialOptions{ClientOptions: *clientOpts, TenantID: sdkConfig.TenantID}
	return azidentity.NewDefaultAzureCredential(opts)
}

// newTokenProvider helps to fetch accessToken for different types of credential. This also takes care of
// refreshing the accessToken before expiry. This accessToken is attached to the Authorization header while making requests.
func newTokenProvider(cfg *AzureADConfig, cred azcore.TokenCredential) (*tokenProvider, error) {
	audience, err := getAudience(cfg.Cloud)
	if err != nil {
		return nil, err
	}

	tokenProvider := &tokenProvider{
		credentialClient: cred,
		options:          &policy.TokenRequestOptions{Scopes: []string{audience}},
	}

	return tokenProvider, nil
}

// getAccessToken returns the current valid accessToken.
func (tokenProvider *tokenProvider) getAccessToken(ctx context.Context) (string, error) {
	tokenProvider.mu.Lock()
	defer tokenProvider.mu.Unlock()
	if tokenProvider.valid() {
		return tokenProvider.token, nil
	}
	err := tokenProvider.getToken(ctx)
	if err != nil {
		return "", errors.New("Failed to get access token: " + err.Error())
	}
	return tokenProvider.token, nil
}

// valid checks if the token in the token provider is valid and not expired.
func (tokenProvider *tokenProvider) valid() bool {
	if len(tokenProvider.token) == 0 {
		return false
	}
	if tokenProvider.refreshTime.After(time.Now().UTC()) {
		return true
	}
	return false
}