Salesforce Service Account Integrations

Problem

You are building interactive or rendered content in Python or R which needs to access a Salesforce resource using an integration user rather than relying on explicit user interaction in an OAuth flow.

Solution

The examples below illustrates how to use the OAuth integrations feature of Posit Connect to delegate authorization to the data provider. These examples use an OAuth access token which identifies the integration user to call the Salesforce API, allowing content to access private resources.

When publishing the content to Connect make sure the following environment variables are set for the deployed content:

  • SALESFORCE_DOMAIN
from posit import connect
import requests
import os

client = connect.Client()

content_session_token =  os.getenv("CONNECT_CONTENT_SESSION_TOKEN")
salesforce_domain = os.getenv("SALESFORCE_DOMAIN") 

# Example API endpoint. Returns information about the user identified by the OAuth access token. 
# In this case, we expect to see a userinfo that identifies the Client Credentials integration user 
# configured in the Salesforce OAuth app.
user_info_endpoint = "https://login.salesforce.com/services/oauth2/userinfo"

client = connect.Client()
access_token = client.oauth.get_content_credentials(content_session_token).get("access_token")
headers = {"Authorization": f"Bearer {access_token}"}

response = requests.get(user_info_endpoint, headers=headers)
response_dict = response.json()
name = response_dict["name"]
greeting = f"Hello, {name}!"

print(greeting)
library(connectapi)
library(dplyr)
library(httr2)

# Obtain a Salesforce OAuth token.
salesforce_token <- function() {
  # init Posit Connect API client
  client <- connect()
  
  # Exchange content session token for Service Account OAuth access token.
  # Connect makes the content session token available in the 
  # environment variable `CONNECT_CONTENT_SESSION_TOKEN`.
  credentials <- get_oauth_content_credentials(client)
  credentials$access_token
}

# Get information about the user.
salesforce_user <- function() {
  domain <- Sys.getenv("SALESFORCE_DOMAIN")
  token <- salesforce_token()
  resp <- httr2::request("https://login.salesforce.com/services/oauth2/userinfo") |>
    httr2::req_auth_bearer_token(token) |>
    httr2::req_retry(max_tries = 2) |>
    httr2::req_perform()
  resp_body <- httr2::resp_body_json(resp)
  resp_body
}
salesforce_user()$name