☰
Salesforce Connected App配置实战:OAuth授权流程与API集成全指南
2026/9/26 7:40:35 网站建设 项目流程

做Salesforce集成的朋友应该都遇到过这个场景:外部系统要读Salesforce的数据,或者你想写个脚本把订单批量推上去,然后网上查了一圈资料,得到的答案几乎都是同一句——"去新建一个Connected App,用OAuth调API就行了"。我刚开始听到这话的时候觉得这事儿挺简单的,直到真正上手才发现,光是配置页面里那七八个按钮和一堆OAuth选项,就足以让人绕半天。

这篇东西就围绕Connected App的设置展开,把我从创建到跑通、再到上线的完整过程捋一遍。这里面既包括每个配置项到底是干嘛的、不同OAuth Flow怎么选,也会把我在实测过程中踩过的坑、排查过的报错一并放出来,给正准备做Salesforce API集成的同学一份可以直接照着操作的参考。

1. Connected App在Salesforce生态里的定位:外部访问的第一道关卡

先说清楚Connected App到底解决什么问题。Salesforce本身是一个多租户的云平台,它对"谁能调用API""通过什么方式调用"做了非常严格的管控。早期那种直接在代码里写用户名密码调API的做法,现在基本行不通了,平台层面要求所有外部应用必须有一个明确的身份标识,并且要走OAuth协议来换取访问令牌。

Connected App本质上是Salesforce体系里的"应用登记卡"。你可以把它理解成小区门口的访客系统:你先把某个外部应用的身份(也就是Connected App)登记到平台里,平台给它发一对钥匙(Consumer Key和Consumer Secret),然后这个应用每次来访问的时候,都要用这对钥匙证明"我是谁",再配合用户授权,确定"我能进哪栋楼、能开哪扇门"。

这个机制带来的直接好处有三个:

  • 身份可追溯:每个API调用都能关联到具体的Connected App和具体用户,出了问题能在Login History、Auth Session里查到来源。
  • 权限可收敛:Connected App可以限定OAuth Scopes,也就是控制这个应用拿到的Token能调哪些接口、访问哪些数据范围,不用把全部权限暴露给外部系统。
  • 审计可落地:平台对Connected App的创建、授权、Token发放都有审计事件,合规要求严格的企业(金融、医疗、零售)很依赖这部分记录。

从我接触过的实际项目看,Connected App最常用的场景集中在以下几类:

  • 系统间数据集成:比如ERP、电商平台、数据中台通过REST API或Bulk API把数据同步到Salesforce。
  • 移动端或PC端工具:公司内部开发的工具需要员工登录后读取其权限范围内的数据。
  • 第三方BI报表工具:Tableau、Power BI或者自研的数据看板需要从Salesforce取数。
  • 自动化脚本和运维任务:定期清洗数据、批量修改记录、同步主数据等场景。

在这些场景里,Connected App承担的角色都不太一样,有的是"服务器到服务器"的系统级身份,有的是"代替某个用户"的用户级身份。搞清楚这个区别,后面选OAuth Flow才不会选错。

2. 创建Connected App:设置页面里每个选项的用途和推荐取值

2.1 入口和基础信息

进入Setup,在顶部搜索框输入"App Manager",打开应用管理界面,然后点击右上角的"New Connected App"按钮。

在这里需要填三样基础信息:

  • Connected App Name:显示名称,比如"ERP_Integration_Prod",建议按"用途+环境"的规则命名,方便后期维护。
  • API Name:系统会自动生成,可以手动改,它是这个Connected App在Metadata层面的唯一标识。
  • Contact Email:必填,用于接收平台的关于这个应用的通知(比如密钥即将过期、异常登录提醒等)。

这里有个小提醒:API Name一旦保存就不能改,所以在前期就要定好命名规范。我见过不少项目因为一开始没规划好,后面在Metadata管理、权限集引用时全是手工维护的旧名称,很痛苦。

2.2 启用OAuth Settings和Consumer Key/Secret的生成逻辑

接下来最关键的一步,勾选"Enable OAuth Settings"。这一步不做,后面的回调地址、Scopes这些配置项全都不会显示。勾选之后,你会看到Callback URL、Selected OAuth Scopes、Require Secret for Web Server Flow等一系列选项。

保存之后,平台会生成Consumer Key(这个类似公钥,到处可见)和Consumer Secret(这个类似私钥,相当于密码)。注意,Consumer Secret只在创建完成后的页面里完整显示一次,之后如果忘了,只能通过点击"Manage Consumer Details"重新获取,而且每次重取都可能使旧的Secret失效,所以在保存那一刻就要把它放到安全的密码管理器里。

2.3 Callback URL:大小写敏感,匹配粒度比你想的更严格

Callback URL,有的地方也叫Redirect URL,是OAuth授权完成后平台把授权码(Authorization Code)跳到哪个地址的配置。这是整个设置里最容易被忽略、也最容易踩坑的字段。

它的匹配规则是完全匹配(exact match),包括协议、域名、端口和路径,甚至大小写都敏感。比如你填了https://app.example.com/callback,授权完平台跳转到https://app.example.com/Callback都会失败。

我踩过一次很典型的坑:本地开发环境用http://localhost:3000/callback调试没问题,部署到生产环境时把回调改成了https://api.example.com/sf/callback,但由于当时的API网关对内网转发时去掉了末尾的斜杠,导致回调URL对不上,OAuth流程一直报redirect_uri不匹配。排查到最后才发现,不是代码问题,就是回调地址在网关上被改写了一个字符。

所以建议是:一个环境对应一个Callback URL,如果有多个回调地址(比如本地、测试、生产),要么用多个Connected App,要么在平台侧尽量把地址统一。Salesforce目前允许你在Token端点通过redirect_uri参数指定多个已注册地址之一,但前提是每个地址都提前注册且完全匹配。

2.4 OAuth Scopes:宁可少给,不要贪多

Scopes决定了这个Connected App换取到的Access Token能调用哪些接口、操作哪些数据。常见的选项有:

Scope含义
Manage user data via APIs (API)允许通过API读写当前用户可访问的数据
Perform requests at any time (RefreshToken)允许签发Refresh Token,刷新过期Access Token
Access unique user identifiers (OpenID)返回OpenID标识信息
Access Salesforce CMS API访问CMS内容
Full access (full)几乎等同于当前用户的全部权限

我个人的建议是,绝大多数场景只勾选第一项"Manage user data via APIs"加"Perform requests at any time"就足够了。凡是勾了"Full access"的项目,后期基本都会面临安全合规的追问——为什么应用需要全部权限?是不是存在过度授权?

还有一个容易踩的点:Scopes的生效范围跟"当前授权用户有权限访问的数据"是取交集的。也就是说,即使Connected App勾了Full access,实际API返回的数据范围仍然不会超出登录用户(或集成用户)本身的Profile、Permission Set、Sharing规则所允许的范围。这一点在权限设计时必须想清楚,否则会出现"明明Connected App看着权限很大,但查不到数据"的情况。

2.5 两个容易被问到的开关:Require Secret和Refresh Token策略

在OAuth Settings里还有几个开关,初看容易不知道什么意思,实际影响不小:

  • Require Secret for Web Server Flow:Web Server Flow(Authorization Code Flow)在换取Token的时候需要带Client Secret。建议开启,这是OAuth 2.0安全基线里的标准做法。
  • Require Secret for Refresh Token Flow:Refresh Token刷新的时候是否要求带Client Secret。同样建议开启。
  • Enable Client Credentials Flow:这个选项是Salesforce后来加入的,适合纯系统到系统、不涉及具体用户授权的场景。勾选后还需要设置"Run As"用户,表示API调用以哪个后台用户身份执行。

2.6 生命周期状态:尝鲜和生产的配置差异

Connected App保存后在界面上会有一个状态标识,默认是"In Development",也就是开发模式。在开发模式下,OAuth流程只能由创建者(或System Administrator)授权使用,其他用户登录授权会被拒绝。

要把它变成所有人可用,需要进入Connected App详情页,点击右上角"Edit",找到"Manage OAuth Policies"区域,把"Permitted Users"改成"Admin-approved users are pre-authorized"或"All users may self-authorize"。前者适合企业内部系统,把User ID或Profile加入允许列表后,用户不用逐个弹窗确认;后者适合面向员工自助集成的场景。

另外再提一个操作细节:如果你想把同一个Connected App配置复制到生产环境,除了在界面上手动填一遍,更靠谱的方式是用Metadata API拉取ConnectedApp对象,或者借助VS Code的Salesforce扩展包、DevOps Center之类的工具做元数据部署。手动配置很容易漏掉某个开关不一致,上线当天才发现生产环境的回调地址不对,那时候就真的手忙脚乱了。

3. 选对授权流程:服务器到服务器、Web应用、无头设备各该用哪种Flow

3.1 几种OAuth Flow的适用场景对比

Connected App设置完成后,紧接着要面对的就是选择OAuth授权流程。Salesforce支持的常见模式有五种,各自有明确的使用边界:

OAuth Flow适用场景关键特征安全注意事项
Web Server Flow(Authorization Code)有后端服务的Web应用需要Client Secret换取Token,支持Refresh Token回调地址必须完全匹配,Secret绝不能暴露在前端
User-Agent Flow纯前端/单页应用隐式授权,不经过后端换取TokenToken暴露在浏览器历史,不建议新项目使用
Username-Password Flow内部工具、测试脚本用户名密码直接换Token无法撤销单个用户的授权,侵入性较强
JWT Bearer Flow服务器到服务器集成用证书签名换取Token,无需用户交互需要配置证书并妥善保管私钥
Device Flow无头设备、CLI工具用户在其他设备上输入授权码完成授权适合交互受限的设备场景

3.2 为什么我强烈建议系统集成优先考虑JWT Bearer Flow

如果你做的是ERP、数据中台、BI取数这类"服务器主动发起"的集成,我的首选是JWT Bearer Flow。理由很简单:它不需要用户名密码在外部系统里存着,也不用专门维护一个用户去授权,安全性比Username-Password高级很多,而且完全无用户交互,适合后台定时任务。

JWT Bearer Flow的核心思路是:你生成一个密钥对(RSA或者X.509证书),把公钥上传到Connected App里,然后用私钥签一个JWT发给Salesforce的Token端点,换取Access Token。JWT里要包含三项关键信息:

  • iss:Connected App的Client ID。
  • sub:集成用户(比如一个专门的Integration User)的Username。
  • aud:Salesforce实例的Token端点,通常是https://login.salesforce.com/services/oauth2/token(生产)或https://test.salesforce.com/services/oauth2/token(沙盒)。

JWT的过期时间(exp)一般设置几分钟内有效,不要设置得太长,建议5分钟以内,换到Access Token之后再由Access Token去调API,这样即使JWT泄露,影响窗口也非常有限。

3.3 JWT Bearer的实操链路

在Connected App端,需要做两件事:

  1. 在Connected App的OAuth Settings里勾选"Enable JWT Bearer Flow"。
  2. 上传证书公钥,也就是在OAuth Settings下方找到"Certificate"区域,上传你生成的证书或公钥文件。

然后服务端代码的流程大概是:加载私钥,构造JWT(包含iss、sub、aud、exp),用RS256算法签名,然后POST到Token端点,收到access_token和instance_url。后续所有API调用都以instance_url为Base URL,Header里带Authorization: Bearer <access_token>。

这里有个细节经常被忽略:JWT里定义的用户的Profile必须勾选"API Enabled"权限,否则Token虽然能拿到,但调用任何API都会返回INVALID_SESSION_ID。我排查过不下三次这个问题,每次都不是JWT写错,而是那个集成用户根本就没开API权限。

3.4 Username-Password和Authorization Code的取舍

有一些场景还是会用Authorization Code Flow,比如你做了一个内部Web工具,员工登录后查自己的数据。这种模式下用户在浏览器里跳转到Salesforce登录页,授权后平台会重定向回你的回调地址并带上授权码,再由后端用授权码加Client Secret换Token。

这个Flow要注意的是,Callback URL必须是你自己控制的地址,而且每次授权都要经过用户点击确认(除非你把Permitted Users设成了Admin预授权)。对于团队员工的内部工具,建议把权限策略设置为"Admin-approved users are pre-authorized",减少弹窗打扰。

至于Username-Password Flow,能用尽量别用。它最大的问题是一旦账号密码在外部系统里存了,任何拿到了这个外部系统权限的人就等于拿到了Salesforce的登录凭据。Salesforce本身对这个Flow的管控也越来越严,在某些Org配置下(比如启用MFA的组织)这个是直接走不通的。

4. 跑通验证:用Postman和脚本实测整个OAuth链路

4.1 用Postman快速验证Authorization Code Flow

配置完Connected App之后,第一件事就是先验证能不能正常换取Token。我一般的做法是用Postman快速跑一遍Authorization Code Flow。

Postman里的OAuth 2.0配置界面可以直接设置Authorization URL、Access Token URL、Client ID和Client Secret,然后在浏览器里完成授权。以生产环境为例:

  • Authorization URL:https://login.salesforce.com/services/oauth2/authorize
  • Access Token URL:https://login.salesforce.com/services/oauth2/token
  • Callback URL:和Connected App配置的一致,比如https://app.example.com/callback

在Postman里填好上面几项后,点"Get New Access Token",会跳出一个Salesforce登录窗口,登录授权完成后拿到Access Token和Refresh Token。这个验证的意义在于确认:

  • Callback URL配置是否正确;
  • Scopes是否满足所需接口;
  • 用户是否有权访问目标对象的数据。

如果这一步顺利,说明Connected App本身没问题,后面代码报错基本可以定位到代码或权限层面。

4.2 用脚本验证JWT Bearer Flow

跑通Authorization Code之后,再验证JWT Bearer Flow。这里给一个Python示例的伪代码思路:

import jwt import requests import time client_id = "3MVG9..." # Consumer Key private_key = open("server.key", "rb").read() username = "integration@example.com" claims = { "iss": client_id, "sub": username, "aud": "https://login.salesforce.com/services/oauth2/token", "exp": int(time.time()) + 300 } token = jwt.encode(claims, private_key, algorithm="RS256") payload = { "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": token } r = requests.post("https://login.salesforce.com/services/oauth2/token", data=payload) auth_data = r.json() access_token = auth_data["access_token"] instance_url = auth_data["instance_url"]

这段代码跑完之后,用instance_url加/services/data/v59.0/sobjects/Account/去调用一次API试试:

curl -X GET \ "https://your_instance.my.salesforce.com/services/data/v59.0/sobjects/Account/" \ -H "Authorization: Bearer <access_token>"

返回200就是通了。如果返回401,看一下是不是sub对应的用户名拼写不对(大小写严格),或者是不是给的沙盒地址却用了生产环境的Token端点。

4.3 拿到Token之后的三类高频报错

跑通不等于万事大吉,实际调用API时会遇到几种情况:

  • INVALID_SESSION_ID:Token失效或格式不对。可能是过期时间、Bearer拼写、或者用户的Session超时策略太短。
  • INSUFFICIENT_ACCESS_OR_READONLY:Connected App的Scope没问题,但当前授权用户对目标对象没有字段级或记录级权限。
  • UNSUPPORTED_GRANT_TYPE:多半是grant_type值写错,或者在Username-Password Flow下填了不支持的参数。

我处理INSUFFICIENT_ACCESS_OR_READONLY的次数最多。之前有个项目,脚本用的集成用户是System Administrator,按理说权限够大了,但实际调用某个自定义对象还是报了权限错误。查到最后发现,那个对象的"Called by Apex Without Sharing"设置没开,而代码里的Apex类又用了WITHOUT SHARING关键字以外的模式调用,导致权限被Sharing规则拦了。这种问题跟Connected App本身没关系,但排查的时候得记住:Connected App只管"你是谁",管不了"你能看到什么"。

4.4 多环境配置保持一致的建议

还有一个非常实际的问题:同一套代码,在沙盒上跑得好好的,切到生产环境就报redirect_uri not registered。十有八九是生产环境的Connected App配置和沙盒环境不一致。

我的做法是,把Connected App的配置模板用一个Markdown文档管理起来,内容包括Callback URL、Scopes、Permitted Users、JWT证书、Token策略等。每次搭建新环境就照着模板核对一遍。有条件的话,用Salesforce的Metadata API直接把ConnectedApp的XML部署到目标环境,最大程度减少手工配置差异。

5. 上线前的安全加固与排查清单:这些细节决定集成能活多久

5.1 密钥管理没有"过度谨慎"这回事

Consumer Secret和JWT私钥是外部访问Salesforce的核心凭证。我见过有团队把Secret直接写在Git仓库的配置文件里,也见过把私钥和代码一起打包。这类做法一旦仓库权限泄露,等于把Salesforce的数据拱手送人。

正确的做法是:

  • Secret和私钥放到专门的密钥管理系统里(比如Vault、KMS、云厂商的Secrets Manager),代码里通过环境变量引用,不硬编码。
  • 定期轮换密钥,尤其是人员变动、项目交接、外部审计之后。
  • Consumer Secret只在创建时显示一次,拿到后立刻归档。

5.2 IP限制和证书固定:给Connected App加上边界

Connected App支持两种安全限制:

  • IP Relaxation / IP限制:限定哪些来源IP可以调用Token端点或API。如果你的集成服务器出口IP是固定的,强烈建议勾选并填上具体的IP段。
  • 同意(Consent)策略:设置用户授权的有效期,可以要求用户定期重新授权。

如果用的是JWT Bearer Flow,控制面还在证书上:私钥在谁手上,谁就能代这个用户发起调用。所以证书的生命周期管理要做起来,临期前提前生成新证书,把旧证书在Connected App里删掉。

5.3 Refresh Token的生命周期比你想象的短

Salesforce的Refresh Token默认180天内有效,而且如果用户在Org里修改了密码、被激活了额外的安全性策略,已签发的Refresh Token可能直接失效。这意味着你的代码一定要处理好Token刷新失败的逻辑:

  • 捕获invalid_grant异常;
  • 主动清理失效的Refresh Token;
  • 必要时提示用户重新走一次授权。

在实际生产中,我经常会遇到因为Refresh Token过期导致定时任务静默失败的情况,日志里全是invalid_grant,但又不影响其他功能,很容易被忽略。建议把Token刷新失败做成一个告警事件,纳入监控体系。

5.4 用审计视角复查整个链路

上线前,最好从审计视角走一遍这些问题:

核查项检查点
最小权限原则Connected App的Scope是否收敛到业务所需的最小集合
集成用户权限集成用户的Profile/Permission Set是否最小化,是否开了API权限
Token生命周期Refresh Token有效期、会话Idle超时时间是否符合内控要求
审计事件是否能看到Connected App的登录记录和OAuth授权历史
多环境一致沙盒/生产环境的Connected App配置是否一致,差异是否有记录

5.5 一个被很多人忽略的细节:Connected App的Owner和后续维护

创建Connected App时的Owner(通常是创建者),在后期会收到平台的安全通知和密钥相关提醒。如果创建了这个App的人已经离职,或者Owner账号被冻结,那这个Connected App的维护就会变得很尴尬。

我建议在项目初期就把Connected App的Owner指定为一个服务账号(Service Account)或团队公共账号,而不是某个具体同事的个人账号。这样即使人员变动,钥匙和权限还在团队控制内,不会出现"前任离职了,Connected App没人能改"的窘境。


最后再分享一个实操里的小经验:在调试Connected App的时候,不要一上来就把所有权限拉到最大。最稳妥的方式是,先用一个专门的集成用户、只勾API Scope、Callback URL先用本地地址跑通,然后逐步收紧配置,一步一步验证。我见过太多项目是"配的时候全开,跑通了再一点点收缩权限",结果收缩的时候发现业务逻辑早就绕过权限依赖了,改起来比一开始做权限规划还费劲。Connected App这个"门禁卡"设计得越干净,后面集成的运维越轻松。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询