無周邊身分驗證 API:私人用戶端的授權代碼和認證流程
針對私人用戶端,例如用戶端-伺服器應用程式,您可以使用「授權代碼和認證流程」(建立於 OAuth 2.0 授權代碼授與類型),來為客戶和合作夥伴設定無周邊登入。
必要版本
| 提供版本:Salesforce Classic 與 Lightning Experience |
| 提供版本:Enterprise、Unlimited 及 Developer Edition |
透過授權代碼與認證流程,您可以控制第三方應用程式的前端登入體驗。您透過 Experience Cloud 網站呼叫 Salesforce 無周邊登入 API 來處理驗證使用者,以及授與受保護 Salesforce 資源存取權的後端工作。透過分隔前端和後端流程,讓您的使用者直接登入及存取 Salesforce 資料,而無需離開應用程式。針對私人用戶端,您需要在瀏覽器中開始流程,並使用伺服器端回呼處理常式完成程式碼交換,以擷取授權代碼並將其交換為存取權杖。
設定此流程前,請先完成下列步驟。
- 完成無周邊身分驗證的先決條件。
- 使用下列其中一個選項將您的平台外應用程式與 Salesforce 整合。
由於您透過 Experience Cloud 網站管理 Salesforce Customer Identity,因此您只能針對使用 Experience Cloud 網站子網域 (例如 https://MyExperienceCloudSite.my.site.com) 的客戶和合作夥伴設定「授權代碼和認證流程」。針對使用 login.salesforce.com 或您組織特定的「我的網域」登入 URL 存取 Salesforce 平台的員工,或是存取 Experience Cloud 網站的員工,您無法設定此流程。
以下是授權代碼和認證流程的範例使用個案。假設您任職於一間旅行公司,該公司將客戶資料儲存在 Salesforce 中。您已建立具有用戶端伺服器結構的自訂應用程式,並想讓使用者可在應用程式中存取過去的旅行預訂。您想同時完整控制登入體驗,以便與您公司的品牌化保持一致。因此,您需要將自訂應用程式設定為外部用戶端應用程式或連線的應用程式,並設定授權代碼和認證流程。
依預設,使用者可輸入其使用者名稱以進行登入。若要提供使用者更多選項,請設定無周邊使用者探索。例如,開發流程讓使用者輸入其電子郵件地址、電話號碼,甚至是訂單號碼。請參閱 無周邊登入不含使用者名稱。
以下是流程實際的簡化概觀。
- 當使用者前往您的自訂應用程式,應用程式內會內建顯示您的登入表單,讓使用者輸入其使用者名稱和密碼。或者,如果您使用無周邊使用者探索,他們會輸入電子郵件地址、電話號碼或訂單號碼等識別碼,以及其密碼。
- 如果您是使用 Proof Key for Code Exchange (PKCE) 擴充功能,則應用程式會產生用於驗證授權代碼的值。如果您沒有使用 PKCE,則流程會略過此步驟。
- 從瀏覽器中,自訂應用程式會透過 JavaScript 將無周邊授權代碼要求傳送至您 Experience Cloud 網站上的 Salesforce 無周邊登入 API 授權端點。
- 如果您使用無周邊使用者探索,則您的 Apex 處理常式會根據使用者用於登入的識別碼尋找使用者。如果使用者認證有效,且使用者具有已驗證的電子郵件地址或電話號碼,則會繼續登入。
- Salesforce 無周邊登入 API 會驗證使用者的認證,並將 302 重新導向傳回至包含授權代碼的預先設定 URL。在瀏覽器中處理 302 重新導向,並在伺服器上將回應無周邊傳遞給預先設定的回呼處理常式。
- 伺服器端回呼處理常式會從 302 重新導向回應擷取授權程式碼和其他參數。接著會透過 Experience Cloud 網站權杖端點的伺服器端 POST 要求來起始程式碼交換。
- 從權杖端點中,Salesforce 無周邊登入 API 會將存取權杖回應傳回給伺服器端回呼處理常式。
- 伺服器端回呼處理常式會處理權杖回應,並將登入狀態傳回至應用程式。此回應可能包含工作階段詳細資料、使用者資訊,且可能包含存取權杖,視您的應用程式設計和安全性狀態而定。
- 瀏覽器會接收登入回應,並建立使用者的工作階段。
- 使用者現在已登入,且在您要求 Salesforce 資料的自訂應用程式中執行動作。例如,他們可以按一下按鈕來存取差旅預訂歷程記錄,該歷程記錄會儲存在 Salesforce Experience Cloud 網站中。
- 您的自訂應用程式會向受保護的 Salesforce 端點 (例如 Salesforce API) 提出已驗證的要求。
- 客戶現在可以在您的自訂應用程式中,存取自己受保護的資料。例如,他們可以查看自己的差旅預訂歷程記錄。
此流程的一個重要元件是用戶端 JavaScript,此 JavaScript 會要求授權並接收存取權杖回應。此範例使用連線的應用程式。
var clientId = '<Connected App Client ID>';
var baseURL = '<Experience Cloud Domain>';
var redirectURL = '<Experience Cloud Domain>/services/apexrest/code/exchange';
function getUserInfo(accessToken, userInfoBaseURL) {
var client = new XMLHttpRequest();
client.open("GET", userInfoBaseURL + "/services/oauth2/userinfo", true);
client.setRequestHeader("Content-Type", "application/json");
client.setRequestHeader("Authorization", "Bearer " + accessToken);
client.send();
client.onreadystatechange = function() {
if(this.readyState == 3) {
response = JSON.parse(client.response);
response.access_token = accessToken;
document.getElementById("json").textContent = JSON.stringify(response, undefined, 2);
document.getElementById("results").style.display="block";
}
}
}
function startLogin() {
var username = document.getElementById('user_name').value;
var password = document.getElementById('password').value;
var encodedUNP = btoa(username + ':' + password);
var client = new XMLHttpRequest();
client.open("POST", baseURL + "/services/oauth2/authorize", true);
client.setRequestHeader("Auth-Request-Type", "Named-User");
client.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
client.setRequestHeader("Authorization", "Basic " + encodedUNP);
client.send("response_type=code_credentials&client_id=" + clientId + "&redirect_uri=" + redirectURL);
client.onreadystatechange = function() {
if(this.readyState == 3) {
console.log("here");
console.log(client.response);
response = JSON.parse(client.response);
if (response.success) {
getUserInfo(response.access_token, baseURL);
}
}
}
return false;
}
另一個重要元件是伺服器端回呼處理常式,此處理常式會擷取程式碼並將其交換為存取權杖。以下是使用公開為 REST 資源之 Apex 類別的範例回呼處理常式。
@RestResource(urlMapping='/code/exchange')
global class CodeExchangeAPI {
@HttpGet
global static ExchangeResponse doGet() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
try {
res.statusCode = 200;
String accessToken = doCodeExchange(req.params.get('code'), req.params.get('sfdc_community_url'));
if (accessToken != null) {
return new ExchangeResponse(accessToken, req.params.get('state'));
} else {
return new ExchangeResponse('Could not parse auth code redirect URI');
}
} catch (Exception e) {
res.statusCode = 500;
return new ExchangeResponse('Could not parse auth code redirect URI');
}
}
global static String doCodeExchange(String code, String communityURL) {
String clientId = 'Connected App Client ID';
String redirectURL = '<Experience Cloud Domain>/services/apexrest/code/exchange';
String clientSecret = null;
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
//Create Code Exchange URL
String url = communityURL + '/services/oauth2/token';
req.setEndpoint(url);
//Post Body
String body = 'grant_type=authorization_code';
body = body + '&client_id=' + clientId;
body = body + '&code=' + code;
if (clientSecret != null) {
body = body + '&client_secret=' + clientSecret;
}
body = body + '&redirect_uri=' + redirectURL;
//URL encode Post Body
String encodedBody = EncodingUtil.urlEncode(body, 'UTF-8');
// Set request body
req.setBody(body);
//Add Headers
req.setHeader('Content-Type','application/x-www-form-urlencoded');
//Send Token Request
HttpResponse res = h.send(req);
if (res.getStatusCode() == 200) {
//Extract Token from Response
Map<String,Object> tokenResponseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
return (String)tokenResponseMap.get('access_token');
} else {
return null;
}
}
// Response Wrapper
global class ExchangeResponse {
String access_token;
String state;
String errMsg;
Boolean success;
public ExchangeResponse(String access_token, String state) {
this.access_token = access_token;
this.state = state;
this.success = true;
}
public ExchangeResponse(String errMsg) {
this.success = false;
this.errMsg = this.errMsg;
}
}
}
以下是此流程的詳細細目。
一般使用者開啟第三方應用程式並登入
您的使用者開啟第三方應用程式並準備登入。您的應用程式中會顯示登入表單,其中包含使用者名稱、密碼欄位和登入按鈕。Salesforce 不會提供此登入表單。表單的外觀與風格由您決定。您的使用者會輸入其使用者名稱與密碼,並按一下登入按鈕。
第三方應用程式產生 code_verifier 和 code_challenge 值 (選擇性)
如果您是使用 Proof Key for Code Exchange (PKCE) 擴充功能,則應用程式會產生用於驗證授權代碼的值。
根據安全性的最佳作法,我們強烈建議在實作授權代碼和認證流程時使用 PKCE 擴充功能。如需 PKCE 的詳細資訊,請參閱由 網際網路工程任務小組 (IETF) 提供的規格RFC 7636: Proof Key for Code Exchange by OAuth Public Clients。
RFC 7636 中定義的 PKCE 規格也包含可在授權要求中傳送的選用 code_challenge_method 參數。Salesforce 會忽略您在此參數中傳送的任何值,並預設為 SHA256。
當您使用伺服器端回呼處理常式實作此流程時,請在連線的應用程式中啟用「需要 Web 伺服器流程的密碼」與「需要重新整理權杖流程的密碼」設定。啟用這些設定後,請確保您的回呼處理常式會保護取用者密碼的安全性。
第三方應用程式無周邊要求的授權代碼
從瀏覽器中,第三方應用程式會使用非同步 Java 與 XML (AJAX) 將無周邊授權要求傳送至 Experience Cloud 網站上的無周邊登入 API 授權端點。如果您未使用無周邊使用者探索,您可以針對此要求使用 GET 或 POST 方法。如果您使用無周邊使用者探索,則僅支援 POST 要求。
在此用戶端 JavaScript 範例中,startLogin 函數會無周邊將 POST 要求傳送至授權端點。
function startLogin() {
var username = document.getElementById('user_name').value;
var password = document.getElementById('password').value;
var encodedUNP = btoa(username + ':' + password);
var client = new XMLHttpRequest();
client.open("POST", baseURL + "/services/oauth2/authorize", true);
client.setRequestHeader("Auth-Request-Type", "Named-User");
client.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
client.setRequestHeader("Authorization", "Basic " + encodedUNP);
client.send("response_type=code_credentials&client_id=" + clientId + "&redirect_uri=" + redirectURL);
client.onreadystatechange = function() {
if(this.readyState == 3) {
console.log("here");
console.log(client.response);
response = JSON.parse(client.response);
if (response.success) {
getUserInfo(response.access_token, baseURL);
}
}
}
return false;
} 針對 GET 與 POST 要求,您必須包含標題 Auth-Request-Type: Named-User。
或者,若要將此流程連線至無周邊來賓流程,您可以包含具有 JWT 型存取權杖的 Uvid-Hint 標頭,其中包含 UVID 值,這是完全由應用程式產生和管理的第 4 版通用唯一識別碼 (UUID)。若要取得具有 UVID 的存取權杖,您必須啟用外部用戶端應用程式來核發 JWT 型存取權杖,並在應用程式上實作無周邊來賓流程。
否。如果您在應用程式上實作來賓使用者流程,您可以選擇性使用此標頭傳遞 JSON Web 權杖 (JWT) 型存取權杖,其中包含與來賓使用者身分繫結的唯一訪客識別碼 (UVID)。透過將 UVID 傳遞給已命名使用者流程,您可以將來自來賓使用者工作階段的內容資訊 (例如使用者的 Cookie 偏好設定) 帶入至已命名使用者工作階段。
您也可以在要求內文中包含 UVID 純文字值。
根據您使用的方法和組態,有時您需要包含具有使用者認證的「基本」類型授權標題。如果您使用 GET 要求,則必須以授權標頭傳送使用者的認證 (使用者名稱和密碼,相互附加並以 Base64 編碼)。以下是範例 GET 要求。
GET /services/oauth2/authorize? HTTP 1.1
Host: MyDomainName.my.site.com
Auth-Request-Type: Named-User
Authorization: Basic <encoded username:password>
response_type=code_credentials&
redirect_uri=https://www.MyDomainName.my.site.com/services/apexrest/code/exchange&
client_id=******&
code_challenge=Y29kZ*******如果您使用 POST 要求,可以將 Base64 編碼的使用者認證包含在授權標頭,也可以將其放在要求內文中。
如果您使用無周邊使用者探索,則不會傳送使用者名稱和密碼。您會改為在 login_hint 參數中傳送識別碼、選擇性自訂資料和密碼。在 POST 要求內文中包含識別碼、自訂資料和密碼。請勿使用 GET 要求。
針對 GET 與 POST 方法,請在授權要求的內文中包含這些必要參數。
| 參數 | 描述 |
|---|---|
client_id |
外部用戶端應用程式或連線應用程式的取用者金鑰。 |
redirect_uri |
在成功驗證後,將使用者重新導向至其中的 URL。重新導向 URI 必須與外部用戶端應用程式「回呼 URL」欄位中的其中一個值相符。否則批准會失敗。 針對私人用戶端,請使用指向伺服器端回呼處理常式的 |
response_type |
應用程式要求的 OAuth 2.0 授與類型。針對「授權代碼和認證流程」,此值必須為 code_credentials。 |
您也可以在授權要求中包含下列選用參數。
| 參數 | 描述 |
|---|---|
code_challenge |
使用 PKCE 擴充功能時為必要。指定權杖要求中 如果在權杖要求中指定
|
scope |
權限,其會定義外部用戶端應用程式或連線應用程式可存取的受保護資源類型。您在建立連線的應用程式時將範圍指派至其中,且在授權流程期間這些範圍會隨附 OAuth 權杖。若您並未包含此參數,則會要求指派給應用程式的全部範圍。若要進一步限制範圍,請在此參數中傳遞指派範圍的子集。如需有效的參數,請參閱 OAuth 範圍。 |
state |
外部 Web 服務要求傳送至回呼 URL 的任何狀態。這個值必須經過 URL 編碼。 |
uvid_hint |
純文字 您也可以透過 |
login_hint |
使用無周邊使用者探索時為必要。您的 Apex 處理常式用來尋找使用者 Salesforce 帳戶的識別碼。例如,在應用程式中收集使用者的訂單編號,並在 login_hint 參數中傳遞。我們會將 login_hint 值直接傳送至您的 Apex 處理常式。 |
customdata |
如果您使用處理自訂資料的無周邊使用者探索處理常式,則為必要。例如,如果您同時將處理常式與處理自訂資料的登入流程搭配使用,則必須在忘記密碼流程中傳遞自訂資料。 包含 Apex 無周邊探索處理常式用來尋找使用者 Salesforce 帳戶之其他資料的 JSON 字串。例如,傳遞使用者地區設定的相關資訊。 |
(選用) 無周邊使用者探索處理常式尋找使用者
如果您使用無周邊使用者探索處理常式,則處理常式會取得 login_hint 和 customdata 參數,並尋找相關聯的使用者。處理常式會確認使用者的電子郵件地址或電話號碼已驗證。
如需範例處理常式,請參閱 Auth.HeadlessUserDiscoveryHandler。
Salesforce 驗證認證並傳回 302 重新導向
Salesforce 無周邊登入 API 會驗證使用者和應用程式的認證,並將 HTTP 302 重新導向傳回至包含授權代碼的預先設定 URL。在瀏覽器中處理 302 重新導向,並將回應無周邊傳送至重新導向 URL,這是您伺服器上預先設定的回呼端點。範例 URL 如下。
https://www.MyDomainName.my.site.com/services/apexrest/code/exchange?code=aPrxC1*******
&sfdc_community_url=https%3A%2F%2FMyDomainName.my.site.com&sfdc_community_id=0DBxxxxxxxxxxxx
回呼處理常式會擷取程式碼並執行程式碼交換
伺服器端回呼處理常式會從 302 重新導向中擷取授權代碼和其他參數。接著會透過將無周邊 POST 要求傳送至權杖端點來啟動程式碼交換。
在範例 Apex REST 回呼處理常式中,doGet 方法會 ⁇ 取程式碼。
@RestResource(urlMapping='/code/exchange')
global class CodeExchangeAPI {
@HttpGet
global static ExchangeResponse doGet() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
try {
res.statusCode = 200;
String accessToken = doCodeExchange(req.params.get('code'), req.params.get('sfdc_community_url'));
if (accessToken != null) {
return new ExchangeResponse(accessToken, req.params.get('state'));
} else {
return new ExchangeResponse('Could not parse auth code redirect URI');
}
} catch (Exception e) {
res.statusCode = 500;
return new ExchangeResponse('Could not parse auth code redirect URI');
}
}
接著,doCodeExchange 方法會傳送權杖要求。
global static String doCodeExchange(String code, String communityURL) {
String clientId = 'Connected App Client ID';
String redirectURL = '<Experience Cloud Domain>/services/apexrest/code/exchange';
String clientSecret = '<ConnecedApp Secret>';
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
//Create Code Exchange URL
String url = communityURL + '/services/oauth2/token';
req.setEndpoint(url);
//Post Body
String body = 'grant_type=authorization_code';
body = body + '&client_id=' + clientId;
body = body + '&code=' + code;
if (clientSecret != null) {
body = body + '&client_secret=' + clientSecret;
}
body = body + '&redirect_uri=' + redirectURL;
//URL encode Post Body
String encodedBody = EncodingUtil.urlEncode(body, 'UTF-8');
// Set request body
req.setBody(body);
//Add Headers
req.setHeader('Content-Type','application/x-www-form-urlencoded');
//Send Token Request
HttpResponse res = h.send(req);
if (res.getStatusCode() == 200) {
//Extract Token from Response
Map<String,Object> tokenResponseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
return (String)tokenResponseMap.get('access_token');
} else {
return null;
}
}
針對存取權杖要求,您只能使用 POST 要求—不支援 GET 要求。您必須包含 Content-Type 標題。在要求內文中包含這些必要參數。
| 參數 | 描述 |
|---|---|
client_id |
外部用戶端應用程式或連線應用程式的取用者金鑰。 |
client_secret |
外部用戶端應用程式或連線應用程式的取用者密碼。 |
code |
授權伺服器會在成功驗證後建立授權代碼,並將其傳遞至用戶端,該授權代碼為短暫的權杖。用戶端會將授權代碼傳送至授權伺服器來取得存取權杖,或者是重新整理權杖。 |
grant_type |
應用程式可以提供用來證明其是安全訪客的驗證類型。針對「授權代碼和認證流程」,此值必須是 authorization_code。 |
redirect_uri |
在成功驗證後,將使用者重新導向至其中的 URL。重新導向 URI 必須與「回呼 URL」欄位中的其中一個值相符。否則批准會失敗。這個值必須經過 URL 編碼。 針對私人用戶端,請使用指向伺服器端回呼處理常式的 |
您也可以在權杖要求中包含下列選用參數。
| 參數 | 描述 |
|---|---|
code_verifier |
使用 PKCE 擴充功能時為必要。指定具有高 ⁇ 度的 128 位元組隨機資料,以難以猜出
|
format |
回應的預期格式。Salesforce 支援這些格式。
|
在 Apex 程式碼中,回應包裝程式會設定最終傳回應用程式的變數,包括成功與錯誤指標。
// Response Wrapper
global class ExchangeResponse {
String access_token;
String state;
String errMsg;
Boolean success;
public ExchangeResponse(String access_token, String state) {
this.access_token = access_token;
this.state = state;
this.success = true;
}
public ExchangeResponse(String errMsg) {
this.success = false;
this.errMsg = this.errMsg;
}
}Salesforce 授與存取權杖
Salesforce 無周邊登入 API 會接收權杖要求,並將存取權杖回應傳回至伺服器端回呼處理常式。以下是 JSON 格式的範例存取權杖回應。
{
"access_token":"*******************",
"sfdc_community_url":"https://MyDomainName.my.site.com",
"sfdc_community_id":"0DBxxxxxxxxxxxx",
"signature":"ts6wm/svX3jXlCGR4uu+SbA04M6qhD1SAgVTEwZ59P4=",
"scope":"openid api",
"id_token":"XXXXXX",
"instance_url":"https://yourInstance.salesforce.com",
"id":"https://yourInstance.salesforce.com/id/00Dxxxxxxxxxxxx/005xxxxxxxxxxxx",
"token_type":"Bearer",
"issued_at":"1667600739962"
}存取權杖回應包含以下必要參數。
| 參數 | 描述 |
|---|---|
access_token
|
OAuth 權杖,外部用戶端應用程式或連線應用程式會使用此權杖來代表用戶端應用程式,要求對受保護資源的存取權。範圍格式的其他權限可能會隨附存取權杖。 |
id
|
身分 URL,此 URL 可用來識別使用者與查詢使用者的詳細資訊。請參閱身分 URL。 |
instance_url
|
指示使用者組織例項的 URL。例如:https://yourInstance.salesforce.com/. |
issued_at
|
建立簽章時的時間戳記,表示為從 1970-01-01T0:0:0Z UTC 開始的毫秒數。 |
signature
|
以 client_secret 簽署的 Base64 編碼 HMAC-SHA256 簽章。簽章可以包含串連的識別碼和 issued_at value,您可以用來確認身分 URL 自伺服器傳送後未變更。 |
sfdc_community_url
|
Experience Cloud 網站的 URL。 |
sfdc_community_id
|
使用者的 Experience Cloud 網站識別碼。 |
token_type
|
Bearer 權杖類型,用於包含存取權杖的所有回應。 |
存取權杖回應也可能包含以下參數。
| 參數 | 描述 |
|---|---|
id_token
|
包含經驗證使用者屬性的已簽署資料結構,屬性內含使用者的唯一識別碼,以及指示權杖核發時間的時間戳記。此權杖也會識別提出要求的用戶端應用程式。請參閱 OpenID Connect 規格。 如果 scope 參數包含 |
refresh_token
|
從 Web 伺服器、使用者代理程式或混合式應用程式權杖流程所取得的權杖。這個值是密碼。採取適當的措施來保護此值。只有在您的外部用戶端應用程式或連線應用程式設定為具有 refresh_token 範圍時,才會傳回此參數。 |
state
|
用戶端所要求的狀態。只有在原始查詢字串中包含 state 參數時,才會包含此值。 |
回呼處理常式會處理權杖回應,並將參數傳回給應用程式
伺服器端回呼處理常式會從回應取得存取權杖。在伺服器端 Apex 程式碼範例中,此程序會在 doCodeExchange 方法中進行,作為傳送權杖要求的一部分。
//Send Token Request
HttpResponse res = h.send(req);
if (res.getStatusCode() == 200) {
//Extract Token from Response
Map<String,Object> tokenResponseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
return (String)tokenResponseMap.get('access_token');
} else {
return null;
}
伺服器端回呼處理常式會將存取權杖和狀態連同使用者資料、權杖和工作階段資料一起傳回至瀏覽器。在此範例中,回應包裝程式會將存取權杖傳回給應用程式。作為最佳作法,建議您設定伺服器來儲存存取權杖、建立應用程式的工作階段,並將工作階段 (而非存取權杖) 傳回應用程式。身為開發人員,您擁有建立工作階段、儲存存取權杖及管理登入狀態的完整控制權,因此您的特定實作由您自行決定。
以下是瀏覽器主控台記錄中成功回應的範例。
{"success":true,"state":"https://MyExperienceCloudSite.my.site.com/","errMsg":null,"access_token":"00*******"}應用程式處理權杖回應並建立使用者工作階段
應用程式會接收權杖回應、進行處理,並建立使用者工作階段。在用戶端 JavaScript 範例中,會透過 getUserInfo 函數處理回應。
function getUserInfo(accessToken, userInfoBaseURL) {
var client = new XMLHttpRequest();
client.open("GET", userInfoBaseURL + "/services/oauth2/userinfo", true);
client.setRequestHeader("Content-Type", "application/json");
client.setRequestHeader("Authorization", "Bearer " + accessToken);
client.send();
client.onreadystatechange = function() {
if(this.readyState == 3) {
response = JSON.parse(client.response);
response.access_token = accessToken;
document.getElementById("json").textContent = JSON.stringify(response, undefined, 2);
document.getElementById("results").style.display="block";
}
}
}
一般使用者已登入並在應用程式中執行動作
您的使用者現在已登入。他們在您的應用程式中執行需要存取 Salesforce 資料的動作。例如,他們按一下按鈕以檢視其儲存在 Salesforce 中的差旅預訂歷程記錄。
應用程式對 Salesforce 端點發出已驗證的呼叫
為存取使用者的 Salesforce 資料,您的應用程式會使用存取權杖來對受保護的 Salesforce 端點 (例如 Salesforce API) 進行驗證呼叫。
一般使用者存取 Salesforce 資料
使用者現在可以存取應用程式中的受保護 Salesforce 資料。例如,他們可以查看自己的差旅預訂歷程記錄。對一般使用者來說,從登入到存取其資料的整個流程,他們都無須離開應用程式。

