Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Agentspace Salesforce with Workforce Identity Federation #1779

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

krishnaji
Copy link

Description

This example code implements a complete OAuth 2.0 flow to authenticate a user with Salesforce, exchange the Salesforce ID token for a Google Cloud access token via Workforce Identity Federation, and then uses that Google Cloud token to make a request to the Discovery Engine API, and prints the results.
Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Follow the CONTRIBUTING Guide.
  • You are listed as the author in your notebook or README file.
    • Your account is listed in CODEOWNERS for the file(s).
  • Make your Pull Request title in the https://www.conventionalcommits.org/ specification.
  • Ensure the tests and linter pass (Run nox -s format from the repository root to format).
  • Appropriate docs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

@krishnaji krishnaji requested a review from a team as a code owner March 2, 2025 17:07
Copy link

google-cla bot commented Mar 2, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @krishnaji, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

This pull request introduces a new example demonstrating how to authenticate with Salesforce, exchange the Salesforce ID token for a Google Cloud access token using Workforce Identity Federation, and then use that Google Cloud token to make a request to the Discovery Engine API. The code implements a complete OAuth 2.0 flow with PKCE. It includes a license file, a README with prerequisites, and a Python script to perform the authentication and API request.

Highlights

  • OAuth 2.0 Flow with PKCE: Implements a complete OAuth 2.0 flow with PKCE to authenticate a user with Salesforce.
  • Workforce Identity Federation: Exchanges the Salesforce ID token for a Google Cloud access token via Workforce Identity Federation.
  • Discovery Engine API Request: Uses the Google Cloud token to make a request to the Discovery Engine API and prints the results.
  • Local HTTP Server for Callback: Sets up a local HTTP server to handle the OAuth 2.0 callback from Salesforce.

Changelog

  • search/agentspace/agentspace-sfdc-workforce-idp-acl/LICENSE
    • Adds the Apache 2.0 license to the project. This file contains the full text of the Apache 2.0 license, which governs the use, reproduction, and distribution of the code.
  • search/agentspace/agentspace-sfdc-workforce-idp-acl/README.md
    • Adds a README file with prerequisites for running the example, including the need for a Salesforce Connector Enabled datastore in Vertex AI Agent Builder and Google Workforce Identity Federation configured with Salesforce as an OIDC provider. Line 3 specifies that the Salesforce OAuth application must have 'Configure ID Token' and 'Include Standard Claims' checked.
  • search/agentspace/agentspace-sfdc-workforce-idp-acl/agentspace-sfdc-workfoce-acl.py
    • Implements the OAuth 2.0 flow, token exchange, and Discovery Engine API request. Line 29-38 defines configuration variables for Salesforce and Google Cloud. Lines 47-72 implements a local HTTP server to handle the OAuth 2.0 callback. Lines 83-161 implements the Salesforce token retrieval process. Lines 164-188 implements the exchange of the Salesforce ID token for a Google Cloud access token. Lines 211-237 implements the Discovery Engine API request using the Google Cloud access token.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Did you know?

The term 'OAuth' is not an acronym. It was a name chosen somewhat arbitrarily during the early development of the protocol.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The code implements an OAuth 2.0 flow with PKCE to authenticate a user with Salesforce, exchange the Salesforce ID token for a Google Cloud access token via Workforce Identity Federation, and then uses that Google Cloud token to make a request to the Discovery Engine API. The implementation appears to be well-structured and addresses the intended functionality.

Merge Readiness

The code appears to be well-structured and implements the intended functionality. However, it's crucial to ensure that all placeholder values are replaced with actual values before merging. Additionally, thoroughly testing the code with valid credentials and configurations is essential to confirm its correctness and security. I am unable to directly approve the pull request, and users should have others review and approve this code before merging.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you re-work this README to have a title and a more detailed tutorial for how to use this code?

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is set at the repo level and is not needed.

@holtskinner
Copy link
Collaborator

holtskinner commented Mar 3, 2025

Copy link
Collaborator

Choose a reason for hiding this comment

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

Rename this file to be agentspace-sfdc-workforce-acl.py

I also recommend changing the folder name to be less verbose/more clear of what it does.

Comment on lines +131 to +140
token_url = f"https://{SALESFORCE_DOMAIN}/services/oauth2/token"
token_data = {
"grant_type": "authorization_code",
"client_id": SALESFORCE_CLIENT_ID,
"client_secret": SALESFORCE_CLIENT_SECRET,
"redirect_uri": SALESFORCE_REDIRECT_URI,
"code": auth_code,
"code_verifier": code_verifier,
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a library from Salesforce to do this instead of using the raw REST API?

Comment on lines +170 to +193
token_url = "https://sts.googleapis.com/v1/token"

data = {
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"audience": f"//iam.googleapis.com/locations/global/workforcePools/{WORKFORCE_POOL_ID}/providers/{WORKFORCE_PROVIDER_ID}",
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
"subject_token_type": "urn:ietf:params:oauth:token-type:id_token",
"subject_token": sf_id_token,
"scope": GOOGLE_SCOPE,
}

if BILLING_PROJECT_NUMBER:
data["options"] = json.dumps({"userProject": BILLING_PROJECT_NUMBER})

try:
response = requests.post(token_url, data=data)
response.raise_for_status()
google_token_response = response.json()
print(
"Google STS Response:", google_token_response
) # Print the entire response
return google_token_response
except requests.exceptions.RequestException as e:
print("Google STS Request Data:", data) # Print the request data
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a library to handle this?

Comment on lines +220 to +233
api_url = f"https://discoveryengine.googleapis.com/v1alpha/projects/{BILLING_PROJECT_NUMBER}/locations/global/collections/default_collection/engines/{DISCOVERY_ENGINE_APP_ID}/servingConfigs/default_search:search"
request_data = {
"query": DISCOVERY_ENGINE_QUERY,
"pageSize": 10,
"spellCorrectionSpec": {"mode": "AUTO"},
"contentSearchSpec": {"snippetSpec": {"returnSnippet": True}},
}

# Make the API request with the Bearer token
headers = {
"Authorization": f"Bearer {google_access_token}",
"Content-Type": "application/json",
}
print("#################### Agent Builder Search Results ##################")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you use the discoveryengine client library for this?

Copy link
Collaborator

@holtskinner holtskinner left a comment

Choose a reason for hiding this comment

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

See comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants