Connected App/User 以及 Production 與 Sandbox 交錯複雜的通用關係
情境說明
先上個 Python Sample Code,再容我慢慢解釋:
- import requests
- from simple_salesforce import Salesforce
- PROD_password = '<PROD_password>'
- PROD_security_token = '<PROD_security_token>'
- PROD_url = 'https://login.salesforce.com/services/oauth2/token'
- STG_password = '<STG_password>'
- STG_security_token = '<STG_security_token>'
- STG_url = 'https://test.salesforce.com/services/oauth2/token'
- prodSecretKeyWith_ProdUsernamePassword = [('grant_type', 'password'),
- ('client_id', '<Production Connected App Client Id>'), #PROD
- ('client_secret', '<Production Connected App Client Secret>'), #PROD
- ('username', 'api@salesforce-note.com'), #PROD
- ('password', '{}{}'.format(PROD_password, PROD_security_token)),
- ('instance_url', 'https://salesforce-note--stg.my.salesforce.com')]
- stgSecretKeyWith_StgUsernamePassword = [('grant_type', 'password'),
- ('client_id', '<Sandbox Connected App Client Id>'), #STG
- ('client_secret', '<Sandbox Connected App Client Secret>'), #STG
- ('username', 'api@salesforce-note.com.stg'), #STG
- ('password', '{}{}'.format(STG_password, STG_security_token)),
- ('instance_url', 'https://salesforce-note--stg.my.salesforce.com')]
- prodSecretKeyWith_StgUsernamePassword = [('grant_type', 'password'),
- ('client_id', '<Production Connected App Client Id>'), #PROD
- ('client_secret', '<Production Connected App Client Secret>'), #PROD
- ('username', 'api@salesforce-note.com.stg'), #STG
- ('password', '{}{}'.format(STG_password, STG_security_token)), #STG
- ('instance_url', 'https://salesforce-note--stg.my.salesforce.com')]
- response = requests.request(url=STG_url, method='POST', data=prodSecretKeyWith_StgUsernamePassword)
- if response.status_code != 200:
- err_msg = 'Salesforce login failed: ({0}) {1}'.format(response.status_code, response.text)
- raise Exception(err_msg)
- print(response.json())
- sf = Salesforce(instance_url=response.json()['instance_url'],
- session_id=response.json()['access_token'])
- data = sf.query(r"SELECT Id FROM Case limit 5")
- print(data)
在透過 Connected App 去取得 access token 的時候,要打進幾個參數。其中有來自 Connected App的 client_id 和 client_secret,也有來自 user account 的 username 和 password。
Connected App 和 User 在不同環境都是各自獨立的,所以 Production 和 Sandbox 都會各有一組。
正常情況下,當然是 Production 就用 Production 的那組, Sandbox 就用 Sandbox 的這組。毋須混用。那什麼時候跑出混用的情況呢?
例如當我有一個外部的系統在跟 Salesforce 做 integration,我這個外部系統也有 Production 和 Sandbox 兩個環境,分別與 Salesforce 的 Production 和 Sandbox 對接。
那為了避免每次 Salesforce Sandbox refresh 後,我這個外部系統這端上記載的Connected App credential 都要重設,那我不如一開始就在外部系統內都設成 Production 的 Connected App credential 就好。反正只有 Sandbox 的 Connected App 會變動,Production 的都從一而終。
所以關鍵就是,到底能不能用 Sandbox 的 user 帳號搭配 Production 的 Connected App 去 access Sandbox 呢?
結論:這種混搭法,可以成功獲得 access token,但這個 access token 卻很難用以操作 sandbox。會遇到這個 error:
{'message': 'This session is not valid for use with the REST API',
'errorCode': 'INVALID_SESSION_ID'}
除非這個 user 在 sandbox 有"use any API client"這個權限,方能不受限制。
補充資料
以下節錄自來自 Salesforce Support 的官方回覆:
--
(about the error: 'This session is not valid for use with the REST API')
Our senior team confirmed that this is working as designed when "Limit API access to only allowlisted connected apps" is enabled.
We also verified this is another org and got the same results.
If you want to use production org's connected app in a sandbox (or any other org ) when API client whitelisting is enabled, the only option you have is to use have the permission "use any api client" in profile or permission set and assign that permission set to the desired users only.
I hope this is this information helps you in your implementation.
Please let me know if you have any further queries or concerns.
--
Our senior team confirmed that this is working as designed when "Limit API access to only allowlisted connected apps" is enabled.
We also verified this is another org and got the same results.
If you want to use production org's connected app in a sandbox (or any other org ) when API client whitelisting is enabled, the only option you have is to use have the permission "use any api client" in profile or permission set and assign that permission set to the desired users only.
I hope this is this information helps you in your implementation.
Please let me know if you have any further queries or concerns.
--
留言
張貼留言