Salesforce Integration Security
The Salesforce integration is a one-way integration that pulls Opportunity records from a customer-authorized Salesforce org and moves them into the GovDash Capture pipeline. When you connect Salesforce, you grant GovDash OAuth access to your CRM, and because Salesforce's api scope is broad, that access can in principle read anything the authorizing user can read. The integration is designed to minimize what it touches, and to give your Salesforce administrator the controls that bound it. This brief describes that access, what happens to the data, and the controls on both sides.
This article is for the Salesforce administrators and security reviewers who approve the connection, and for the GovDash administrators who configure it. Screen-by-screen setup, phase linking, and field mapping live in Salesforce Pipeline Integration Setup & Troubleshooting.
Data flow overview
The connecting user's browser completes the Salesforce login and consent screen at
https://login.salesforce.com, then returns to GovDash with an authorization code. GovDash's servers exchange that code for tokens; the connected app's client secret never leaves our servers.On each sync, GovDash's servers call the org's instance URL (typically
https://<my-domain>.my.salesforce.com) over HTTPS to describe the Opportunity object and query the mapped fields on opportunities in linked stages.Only the queried fields on those records leave Salesforce. They are stored as Unclassified opportunities scoped to the GovDash team that connected the org. Nothing is written back to Salesforce.
CUI handling
Opportunities created from this integration are stored as Unclassified. The sync does not inspect Salesforce values for CUI, and it does not mark imported records as CUI.
Map and sync fields that are appropriate for an Unclassified GovDash opportunity. Keep CUI, and other data the team is not prepared to store as Unclassified, off the mapped Opportunity fields. If a record needs a different classification after import, that change is a GovDash data-handling step, not something the Salesforce sync does.
GovDash does not accept data classified above CUI.
Risks we designed around
The integration was designed around three risks, each with a control in place:
If stored OAuth tokens were ever exposed. Tokens are encrypted at rest, scoped to a user and team, and revocable from either side.
Access that is broader than needed. Salesforce does not offer an OAuth scope that means "read Opportunity only," so the
apiscope token is as broad as the authorizing user. The control is a dedicated, least-privilege integration user.If GovDash systems were ever breached. Imported opportunity data and stored credentials are stored encrypted at rest and scoped to the team that connected the org.
The controls are described in detail below.
Access to your Salesforce Org
OAuth scopes
The connection uses Salesforce's OAuth 2.0 web-server (authorization code) flow. The GovDash connected app is configured with two scopes:
Salesforce scope | How GovDash uses it |
|---|---|
| Lets GovDash call the Salesforce REST API as the user who approved the connection. This is how GovDash reads the org name, Opportunity field metadata, the stage picklist, and Opportunity records. |
| Lets Salesforce return a refresh token so scheduled sync can run when that user is not signed in to GovDash. |
Once the user approves, Salesforce issues a short-lived access token and a longer-lived refresh token. GovDash encrypts both and stores them against the connecting user and team. The access token makes API calls to the org; the refresh token obtains new access tokens when the current one expires.
The OAuth callback uses standard CSRF protections, including a single-use, short-lived state nonce bound to the connecting user and session. Sensitive callback parameters are kept out of logs.
Salesforce API calls GovDash makes
Call | Why |
|---|---|
Read the Organization name | Records which Salesforce org was connected. A GovDash team can be connected to one Salesforce org at a time. |
Describe Opportunity | Lists fields so an admin can map them, and reads the active Stage picklist so phases can be linked. |
Query Opportunity | Imports opportunities whose stage is one of the stages linked to a GovDash phase. The query selects |
GovDash does not create, update, or delete Salesforce records with this connection. It does not query other objects (Account, Contact, Lead, Task, Content, or Chatter), and it does not subscribe to platform events or change data capture.
The integration user is the boundary
The api scope is broad in Salesforce's model. A user who can read other objects in Salesforce could, in principle, be used by a different client with the same token. The control for that is the integration user, and we recommend enforcing the one-way design in Salesforce itself:
Use a dedicated integration user rather than a person's account.
Grant it read-only access to Opportunity - no create, edit, or delete - so "one-way" holds even if the token is ever misused.
Grant field-level security only on the fields you intend to sync. A field the user cannot read is absent from the query result, so GovDash cannot import it.
Withhold access you do not want available to the token.
Sharing rules apply. An integration user with View All Data, or a System Administrator, causes GovDash to import every opportunity in the linked stages. An integration user with private sharing imports only the opportunities shared with that user. After import, Salesforce sharing no longer applies, visibility inside GovDash follows GovDash roles.
What the Salesforce user needs
Requirement | Why |
|---|---|
API Enabled | Salesforce rejects REST calls from a user without this permission. |
Read on Opportunity | The sync queries Opportunity. Records the user cannot see are not returned. |
Field-level security on each mapped field | A field the user cannot read is absent from the query result, so GovDash cannot import it. |
Read on Organization | Used once, at connect time, to store the org name. |
Permission to authorize the GovDash connected app | Required on the first connect, and again if the org requires admin-approved connected apps. The setup guide covers Approve Uninstalled Connected Apps and installing the app from Connected Apps OAuth Usage. |
Connected app policies
Recommended policies on the GovDash connected app, matching the setup guide:
Policy | Recommended setting | Why |
|---|---|---|
Permitted Users | All users may self-authorize, after an admin has installed the app | The connecting user has to be allowed to approve the app. Pre-authorize specific users or permission sets if the org requires admin-approved apps. |
Refresh Token Policy | Keep a durable refresh token | Auto sync depends on a refresh token that remains valid between runs. A policy that expires or invalidates the refresh token will pause sync until someone reconnects. Your GovDash setup guide covers the exact settings for your org. |
GovDash permissions
GovDash permission | Why |
|---|---|
Manage Settings in Capture | Connect or disconnect Salesforce, map fields, link or unlink phases, choose Create Only or Override, run a sync, and turn auto sync on or off. |
Read in Capture | View the opportunities after they are imported. |
What is imported, and why
Only Opportunity records are imported, and only when their stage is linked to a GovDash capture phase. Opportunities in unlinked stages stay in Salesforce.
On first connect, GovDash creates these default mappings. Opportunity Name and Phase are fixed. The others can be removed or pointed at a different Opportunity field.
Salesforce field | GovDash field | Why it is imported |
|---|---|---|
| Opportunity Name | Every imported opportunity needs a name. This mapping cannot be removed. |
| Phase | Places the opportunity in the pipeline, and is the filter for which records sync. This mapping cannot be removed. |
| Value (USD) | Pipeline value. |
| Due Date | The opportunity due date. |
| Description | The opportunity description shown in Capture. |
| External CRM Identifier ID | Optional. Present in the default mapping, and left disconnected until the field exists on Opportunity. See Matching records that already exist in both systems. |
An admin can map additional Opportunity fields in Track Salesforce Fields:
GovDash field | Typical use |
|---|---|
Posted Date, Original Posted Date | Solicitation dates stored on the opportunity. |
Solicitation Number | Matched to a solicitation number GovDash already knows. |
NAICS, PSC, Set Aside | Matched to GovDash's reference lists. A value that does not match is left empty. |
Role |
|
Anticipated Contract Type, Notice Type | Matched to GovDash's values for those fields. |
A GovDash custom field | Text, long text, URL, number, currency, percentage, date, checkbox, or single-select. |
These GovDash custom field types cannot be a sync destination: number range, currency range, date range, multi-select, formula, and rating.
Matching records that already exist in both systems
GovDash reads an optional custom field. It does not write that field.
Setting | Value |
|---|---|
Object | Opportunity |
Field label | GovDash Opportunity ID |
API name |
|
Type | Text |
Length | 64 |
Unique | Yes |
When that field contains a GovDash opportunity id, sync attaches the Salesforce opportunity to the existing GovDash record instead of creating a second one. The customer's team fills the field in Salesforce. Map it to External CRM Identifier ID in Track Salesforce Fields.
Sync behavior inside GovDash
Setting | What it does |
|---|---|
Create Only | Creates a GovDash opportunity the first time a Salesforce opportunity is seen. Later Salesforce edits do not overwrite the GovDash record. This is the recommended default. |
Override | Salesforce is the source of truth for mapped fields. Each sync updates those fields on the matching GovDash opportunity, and moves it to the GovDash phase linked to its Salesforce stage. A mapped field someone has edited by hand in GovDash, or that is tied to an uploaded document, is left as the team set it. Phase still follows the Salesforce stage. |
One-time sync | Imports the current matching opportunities once. |
Auto sync | Every 30 minutes, for teams that have linked phases, turned auto sync on, and still have a healthy connection. The job runs using the Salesforce connection authorized by the GovDash user who enabled auto sync. |
Link phases | Copies Salesforce's active opportunity stages into the GovDash pipeline (names, order, and colors the admin confirms). GovDash phases that are not mapped are kept and unlinked. Salesforce stages are not changed. |
Unlink phases | Clears the stage links and turns auto sync off. |
Minimizing data stored
On connect, GovDash stores:
Salesforce user id, org id, and org name.
The org's instance URL.
An access token and a refresh token for that user, encrypted at rest.
On each sync, for opportunities in linked stages that the connected user can see:
Salesforce opportunity id and stage.
The default fields (name, amount, close date, description), unless an admin has removed those mappings.
Any additional Opportunity fields an admin has mapped, including custom fields and formula fields used to flatten lookups.
The GovDash opportunity id, when
GovDash_Opportunity_ID__cis populated and mapped.
GovDash does not import files, attachments, Chatter, emails, or related-object records through this connection.
Imported opportunities are stored with source Salesforce. Disconnecting Salesforce does not delete opportunities already imported. Those records stay until the team deletes them in GovDash. Stored tokens are deleted on disconnect, and when the last connected user for an org disconnects, the stored org link and field mappings are deleted too.
Protecting stored data
The access token and refresh token are encrypted with FIPS-validated cryptography before they are stored. They are stored for the GovDash user and team that connected, and are not readable by other teams.
Imported opportunities are scoped to the GovDash team that connected the org. Another team's users cannot read them. Who on the team can see them follows GovDash roles (Read in Capture, and any finer capture permissions the team has configured).
GovDash also offers outbound webhooks. Webhooks are only supported for unclassified records.
Granting and revoking access
Either side can cut off access:
In GovDash, Disconnect Salesforce Account deletes the stored tokens for that user. If that user was the one who enabled auto sync, auto sync turns off. When the last connected user for the org disconnects, GovDash also deletes the stored org link and field mappings.
In Salesforce, revoke the GovDash connected app or the user's session from Connected Apps OAuth Usage. The next sync fails. A deactivated Salesforce user, or an instance URL Salesforce no longer serves, marks the connection unhealthy and pauses scheduled sync until someone reconnects.
Auto sync also turns off if the GovDash user who enabled it is removed from the team, even if their Salesforce connection was never disconnected.
Reconnect from GovDash (the button is labeled Reconnect Salesforce while the connection is unhealthy) to issue a new token and mark the connection healthy again.
Operational notes
Scheduled sync runs every 30 minutes for orgs that have auto sync on, at least one linked phase, and a healthy connection. A one-time sync is available from Capture Settings without turning auto sync on.
The connection is marked unhealthy, and scheduled sync pauses, when Salesforce reports the authorizing user is inactive, when the instance URL is no longer reachable, or when the stored credentials cannot be decrypted. GovDash notifies the team and leaves the connection paused until someone reconnects.