Keycloak JavaScript 介面卡

可用於保護網頁應用程式安全的用戶端 JavaScript 程式庫。

Keycloak 隨附一個名為 keycloak-js 的用戶端 JavaScript 程式庫,可用於保護網頁應用程式的安全。此介面卡也內建支援 Cordova 應用程式。

安裝

我們建議您從 NPM 安裝 keycloak-js 套件

npm install keycloak-js

Keycloak 伺服器設定

關於使用用戶端應用程式,一個重要的考量是,用戶端必須是公開用戶端,因為沒有安全的方法可以在用戶端應用程式中儲存用戶端憑證。此考量使得確保您為用戶端設定的重新導向 URI 正確且盡可能具體變得非常重要。

若要使用介面卡,請在 Keycloak 管理主控台中為您的應用程式建立用戶端。在「功能設定」頁面上,將用戶端驗證切換為關閉,使該用戶端成為公開用戶端。

您也需要設定 Valid Redirect URIsWeb Origins。請盡可能具體,因為未能如此做可能會導致安全性漏洞。

使用介面卡

以下範例顯示如何初始化介面卡。請務必將傳遞至 Keycloak 建構函式的選項,取代為您已設定的用戶端的選項。

import Keycloak from 'keycloak-js';

const keycloak = new Keycloak({
    url: "http://keycloak-server",
    realm: "my-realm",
    clientId: "my-app"
});

try {
    const authenticated = await keycloak.init();
    if (authenticated) {
        console.log('User is authenticated');
    } else {
        console.log('User is not authenticated');
    }
} catch (error) {
    console.error('Failed to initialize adapter:', error);
}

若要驗證,您需要呼叫 login 函式。有兩種選項可讓介面卡自動驗證。您可以將 login-requiredcheck-sso 傳遞至 init() 函式。

  • 如果使用者已登入 Keycloak,login-required 會驗證用戶端,如果使用者未登入,則會顯示登入頁面。

  • 只有在使用者已登入時,check-sso 才會驗證用戶端。如果使用者未登入,則瀏覽器會重新導向回應用程式,且保持未驗證狀態。

您可以設定靜默 check-sso 選項。啟用此功能後,您的瀏覽器不會執行完整重新導向至 Keycloak 伺服器並返回您的應用程式,而是會在隱藏的 iframe 中執行此動作。因此,您的應用程式資源只會由瀏覽器載入和剖析一次,也就是在應用程式初始化時,而不是在從 Keycloak 重新導向回應用程式之後。此方法在 SPA (單頁應用程式) 的情況下特別有用。

若要啟用靜默 check-sso,您需要在 init 方法中提供 silentCheckSsoRedirectUri 屬性。請確保此 URI 是應用程式中的有效端點;必須將其設定為 Keycloak 管理主控台中用戶端的有效重新導向。

await keycloak.init({
    onLoad: 'check-sso',
    silentCheckSsoRedirectUri: `${location.origin}/silent-check-sso.html`
});

在成功檢查您的驗證狀態並從 Keycloak 伺服器擷取權杖後,會在 iframe 中載入靜默檢查 SSO 重新導向 URI 的頁面。它沒有其他任務,只是將接收到的權杖傳送至主要應用程式,且應如下所示:

<!doctype html>
<html>
<body>
    <script>
        parent.postMessage(location.href, location.origin);
    </script>
</body>
</html>

請記住,此頁面必須由您的應用程式在 silentCheckSsoRedirectUri 中指定的位置提供服務,而且不是介面卡的一部分。

靜默 check-sso 功能在某些現代瀏覽器中受到限制。請參閱具有追蹤保護的現代瀏覽器章節

若要啟用 login-required,請將 onLoad 設定為 login-required 並傳遞至 init 方法

await keycloak.init({
    onLoad: 'login-required'
});

在使用者經過驗證後,應用程式可以透過在 Authorization 標頭中包含持有者權杖,向 Keycloak 保護的 RESTful 服務發出請求。例如

async function fetchUsers() {
    const response = await fetch('/api/users', {
        headers: {
            accept: 'application/json',
            authorization: `Bearer ${keycloak.token}`
        }
    });

    return response.json();
}

需要記住的一件事是,存取權杖依預設具有較短的存留期,因此您可能需要在傳送請求之前重新整理存取權杖。您可以透過呼叫 updateToken() 方法來重新整理此權杖。此方法會傳回 Promise,讓您可以在權杖成功重新整理時輕鬆叫用服務,如果未重新整理,則會向使用者顯示錯誤。例如

try {
    await keycloak.updateToken(30);
} catch (error) {
    console.error('Failed to refresh token:', error);
}

const users = await fetchUsers();

存取權杖和重新整理權杖都會儲存在記憶體中,且不會以任何形式儲存。因此,絕不應儲存這些權杖,以防止劫持攻擊。

工作階段狀態 iframe

依預設,介面卡會建立一個隱藏的 iframe,用於偵測是否已發生單一登出。此 iframe 不需要任何網路流量。相反地,會透過查看特殊狀態 Cookie 來擷取狀態。可以透過在傳遞至 init() 方法的選項中設定 checkLoginIframe: false 來停用此功能。

您不應依賴直接查看此 Cookie。其格式可能會變更,而且它也與 Keycloak 伺服器的 URL 相關聯,而非您的應用程式。

工作階段狀態 iframe 功能在某些現代瀏覽器中受到限制。請參閱具有追蹤保護的現代瀏覽器章節

隱含和混合流程

依預設,介面卡會使用授權碼流程。

使用此流程時,Keycloak 伺服器會將授權碼 (而不是驗證權杖) 傳回給應用程式。在瀏覽器重新導向回應用程式後,JavaScript 介面卡會將 code 交換為存取權杖和重新整理權杖。

Keycloak 也支援隱含流程,在 Keycloak 成功驗證後立即傳送存取權杖。與標準流程相比,此流程的效能可能較佳,因為沒有額外的請求可將程式碼交換為權杖,但在存取權杖過期時會產生影響。

但是,在 URL 片段中傳送存取權杖可能會造成安全性漏洞。例如,權杖可能會透過網路伺服器記錄或瀏覽器歷程記錄洩漏。

若要啟用隱含流程,請在 Keycloak 管理主控台中啟用用戶端的啟用隱含流程旗標。您也可以將具有值 implicit 的參數 flow 傳遞至 init 方法

await keycloak.init({
    flow: 'implicit'
})

請注意,只會提供存取權杖,而且沒有重新整理權杖。這種情況表示,一旦存取權杖過期,應用程式必須再次重新導向至 Keycloak 才能取得新的存取權杖。

Keycloak 也支援混合流程。

此流程需要用戶端在管理主控台中同時啟用標準流程隱含流程。然後,Keycloak 伺服器會將程式碼和權杖傳送至您的應用程式。可以立即使用存取權杖,而程式碼則可以交換為存取權杖和重新整理權杖。與隱含流程類似,混合流程對於效能而言很有幫助,因為可以立即使用存取權杖。但是,權杖仍然會在 URL 中傳送,而且先前提及的安全性漏洞可能仍然適用。

混合流程的一個優點是,重新整理權杖可供應用程式使用。

對於混合流程,您需要將具有值 hybrid 的參數 flow 傳遞至 init 方法

await keycloak.init({
    flow: 'hybrid'
});

使用 Cordova 的混合應用程式

Keycloak 支援使用 Apache Cordova 開發的混合行動應用程式。介面卡有兩種模式:cordovacordova-native

預設值為 cordova,如果未明確設定任何介面卡類型,且存在 window.cordova,則介面卡會自動選取此值。登入時,它會開啟一個 InApp 瀏覽器,讓使用者與 Keycloak 互動,然後透過重新導向至 https://127.0.0.1 返回應用程式。由於此行為,您會在管理主控台的用戶端設定區段中,將此 URL 列入允許的重新導向 URI。

雖然此模式容易設定,但也存在一些缺點

  • InApp 瀏覽器是嵌入在應用程式中的瀏覽器,而不是手機的預設瀏覽器。因此,它會有不同的設定,且儲存的憑證將無法使用。

  • InApp 瀏覽器也可能較慢,尤其是在呈現更複雜的主題時。

  • 在使用此模式之前,有一些安全性考量需要考慮,例如應用程式可以存取使用者的憑證,因為它完全控制了轉譯登入頁面的瀏覽器,因此請勿在您不信任的應用程式中使用此模式。

替代模式是 `cordova-native`,它採用不同的方法。它會使用系統的瀏覽器開啟登入頁面。使用者驗證後,瀏覽器會使用特殊 URL 重新導向回應用程式。從這裡,Keycloak 介面卡可以透過從 URL 讀取程式碼或權杖來完成登入。

您可以將介面卡類型 cordova-native 傳遞至 init() 方法,來啟用原生模式

await keycloak.init({
    adapter: 'cordova-native'
});

此介面卡需要兩個額外的外掛程式

連結至應用程式的技術細節在每個平台上都不同,而且需要特殊設定。如需進一步指示,請參閱 deeplinks 外掛程式文件的 Android 和 iOS 章節。

存在不同種類的連結可用於開啟應用程式

雖然前者較容易設定且往往運作更可靠,但後者因為是獨一無二的,且只有網域擁有者才能註冊,因此提供了額外的安全性。自訂 URL 在 iOS 上已棄用。為了獲得最佳可靠性,我們建議您使用通用連結,並結合使用自訂 URL 連結的備用網站。

此外,我們建議採取以下步驟來改善與轉接器的相容性

  • 在 iOS 上,通用連結似乎在將 response-mode 設定為 query 時運作更可靠

  • 為了防止 Android 在重新導向時開啟應用程式的新實例,請將以下程式碼片段新增至 config.xml

<preference name="AndroidLaunchMode" value="singleTask" />

自訂轉接器

在某些情況下,您可能需要在預設不支援的環境中執行轉接器,例如 Capacitor。若要在這些環境中使用 JavasScript 用戶端,您可以傳遞自訂轉接器。例如,第三方程式庫可以提供此類轉接器,使其能夠可靠地執行轉接器

import Keycloak from 'keycloak-js';
import KeycloakCapacitorAdapter from 'keycloak-capacitor-adapter';

const keycloak = new Keycloak({
    url: "http://keycloak-server",
    realm: "my-realm",
    clientId: "my-app"
});

await keycloak.init({
    adapter: KeycloakCapacitorAdapter,
});

此特定套件不存在,但它提供了一個很好的範例,說明如何將此類轉接器傳遞到用戶端。

您也可以建立自己的轉接器,若要這樣做,您必須實作 KeycloakAdapter 介面中描述的方法。例如,以下 TypeScript 程式碼可確保所有方法都已正確實作

import Keycloak, { KeycloakAdapter } from 'keycloak-js';

// Implement the 'KeycloakAdapter' interface so that all required methods are guaranteed to be present.
const MyCustomAdapter: KeycloakAdapter = {
    async login(options) {
        // Write your own implementation here.
    }

    // The other methods go here...
};

const keycloak = new Keycloak({
    url: "http://keycloak-server",
    realm: "my-realm",
    clientId: "my-app"
});

await keycloak.init({
    adapter: MyCustomAdapter,
});

當然,您也可以在不使用 TypeScript 的情況下執行此操作,方法是省略類型資訊,但確保正確實作介面的責任將完全由您承擔。

具有追蹤保護的現代瀏覽器

在某些瀏覽器的最新版本中,會套用各種 Cookie 政策,以防止第三方(例如 Chrome 中的 SameSite 或完全封鎖的第三方 Cookie)追蹤使用者。這些政策可能會變得更加嚴格,並隨著時間推移被其他瀏覽器採用。最終,第三方環境中的 Cookie 可能會完全不被支援,並被瀏覽器封鎖。因此,受影響的轉接器功能最終可能會被棄用。

轉接器依賴第三方 Cookie 來實現 Session Status iframe、無聲 check-sso 以及部分用於常規(非無聲)check-sso。這些功能的功能有限,或者根據瀏覽器對 Cookie 的限制程度而完全停用。轉接器會嘗試偵測此設定並做出相應的反應。

具有「預設 SameSite=Lax」政策的瀏覽器

如果在 Keycloak 端和應用程式端都設定了 SSL / TLS 連線,則支援所有功能。例如,Chrome 從 84 版開始會受到影響。

封鎖第三方 Cookie 的瀏覽器

如果轉接器偵測到此類瀏覽器行為,則不支援 Session Status iframe,且會自動停用。這表示轉接器無法使用工作階段 Cookie 來偵測單一登出,而必須完全依賴權杖。因此,當使用者在另一個視窗中登出時,使用轉接器的應用程式將不會登出,直到應用程式嘗試重新整理存取權杖為止。因此,請考慮將存取權杖的存留時間設定為相對較短的時間,以便盡快偵測到登出。如需更多詳細資訊,請參閱工作階段和權杖逾時

預設情況下,不支援無聲 check-sso,並且會回退到常規(非無聲)check-sso。可以透過在傳遞給 init 方法的選項中設定 silentCheckSsoFallback: false 來變更此行為。在這種情況下,如果偵測到瀏覽器的限制性行為,check-sso 將會完全停用。

常規 check-sso 也會受到影響。由於不支援 Session Status iframe,因此在初始化轉接器時,必須額外重新導向至 Keycloak,以檢查使用者的登入狀態。此檢查與使用 iframe 來判斷使用者是否已登入的標準行為不同,且僅在使用者登出時才會執行重新導向。

例如,從 13.1 版開始,Safari 就是一個會受到影響的瀏覽器。

API 參考

建構函式

// Recommended way to initialize the adapter.
new Keycloak({
    url: "http://keycloak-server",
    realm: "my-realm",
    clientId: "my-app"
});

// Alternatively a string to the path of the `keycloak.json` file.
// Has some performance implications, as it will load the keycloak.json file from the server.
// This version might also change in the future and is therefore not recommended.
new Keycloak("http://keycloak-server/keycloak.json");

屬性

authenticated

如果使用者已驗證,則為 true,否則為 false

token

可以在對服務的要求中以 Authorization 標頭傳送的 base64 編碼權杖。

tokenParsed

剖析為 JavaScript 物件的權杖。

subject

使用者 ID。

idToken

base64 編碼的 ID 權杖。

idTokenParsed

剖析為 JavaScript 物件的 ID 權杖。

realmAccess

與權杖關聯的領域角色。

resourceAccess

與權杖關聯的資源角色。

refreshToken

可用於擷取新權杖的 base64 編碼重新整理權杖。

refreshTokenParsed

剖析為 JavaScript 物件的重新整理權杖。

timeSkew

瀏覽器時間與 Keycloak 伺服器之間的估計時間差(以秒為單位)。此值僅為估計值,但在判斷權杖是否已過期時已足夠精確。

responseMode

在 init 中傳遞的回應模式(預設值為 fragment)。

flow

在 init 中傳遞的流程。

adapter

可讓您覆寫程式庫處理重新導向和其他與瀏覽器相關的功能的方式。可用選項

  • 「預設」- 程式庫使用瀏覽器 API 進行重新導向(這是預設值)

  • 「cordova」- 程式庫將嘗試使用 InAppBrowser cordova 外掛程式來載入 keycloak 登入/註冊頁面(當程式庫在 cordova 生態系統中運作時,會自動使用此選項)

  • 「cordova-native」- 程式庫嘗試使用手機的系統瀏覽器,透過 BrowserTabs cordova 外掛程式開啟登入和註冊頁面。這需要額外設定才能重新導向回應用程式(請參閱使用 Cordova 的混合應用程式)。

  • 「custom」- 可讓您實作自訂轉接器(僅適用於進階使用案例)

responseType

在登入要求時傳送至 Keycloak 的回應類型。這會根據初始化期間使用的流程值來決定,但可以透過設定此值來覆寫。

方法

init(options)

呼叫以初始化轉接器。

選項是一個 Object,其中

  • useNonce - 新增加密 nonce 以驗證驗證回應是否與要求相符(預設值為 true)。

  • onLoad - 指定在載入時要執行的動作。支援的值為 login-requiredcheck-sso

  • silentCheckSsoRedirectUri - 如果 onLoad 設定為 'check-sso',則設定無聲驗證檢查的重新導向 URI。

  • silentCheckSsoFallback - 當瀏覽器不支援無聲 check-sso 時,啟用回退至常規 check-sso(預設值為 true)。

  • token - 設定權杖的初始值。

  • refreshToken - 設定重新整理權杖的初始值。

  • idToken - 設定 ID 權杖的初始值(僅與權杖或重新整理權杖一起使用)。

  • scope - 設定 Keycloak 登入端點的預設範圍參數。使用以空格分隔的範圍清單。這些範圍通常參考在特定用戶端上定義的用戶端範圍。請注意,轉接器會永遠將範圍 openid 新增至範圍清單。例如,如果您輸入範圍選項 address phone,則對 Keycloak 的要求將會包含範圍參數 scope=openid address phone。請注意,如果 login() 選項明確指定範圍,則此處指定的預設範圍會被覆寫。

  • timeSkew - 設定本機時間與 Keycloak 伺服器之間的偏移的初始值(以秒為單位)(僅與權杖或重新整理權杖一起使用)。

  • checkLoginIframe - 設定為啟用/停用監控登入狀態(預設值為 true)。

  • checkLoginIframeInterval - 設定檢查登入狀態的間隔(預設值為 5 秒)。

  • responseMode - 設定在登入要求時傳送至 Keycloak 伺服器的 OpenID Connect 回應模式。有效值為 queryfragment。預設值為 fragment,這表示在成功驗證後,Keycloak 會將 OpenID Connect 參數新增至 URL 片段,重新導向至 JavaScript 應用程式。一般而言,這比 query 更安全且更受推薦。

  • flow - 設定 OpenID Connect 流程。有效值為 standardimplicithybrid

  • enableLogging - 啟用從 Keycloak 到主控台的記錄訊息(預設值為 false)。

  • pkceMethod - 要使用的 Proof Key Code Exchange(PKCE)方法。設定此值會啟用 PKCE 機制。可用選項

    • 「S256」- 基於 SHA256 的 PKCE 方法(預設)

    • false - 停用 PKCE。

  • acrValues - 產生 acr_values 參數,該參數是指驗證內容類別參考,並允許用戶端宣告所需保證等級需求,例如驗證機制。請參閱OpenID Connect MODRNA 驗證設定檔 1.0 的第 4 節:acr_values 要求值和保證等級

  • messageReceiveTimeout - 設定等待來自 Keycloak 伺服器的訊息回應的逾時時間(以毫秒為單位)。例如,這用於在檢查第三方 Cookie 期間等待訊息時。預設值為 10000。

  • locale - 當 onLoad 為「login-required」時,依照OIDC 1.0 規格的第 3.1.2.1 節,設定「ui_locales」查詢參數。

傳回在初始化完成時解析的 Promise。

login(options)

重新導向至登入表單,傳回 Promise。

選項是一個選用的 Object,其中

  • redirectUri - 指定在登入後要重新導向的 URI。

  • prompt - 此參數允許在 Keycloak 伺服器端稍微自訂登入流程。例如,若值為 login,則強制顯示登入畫面。或者,若客戶端具有「需要同意」 (Consent Required) 設定,則值為 consent 時,會強制顯示同意畫面。最後,可以使用值 none 來確保不向使用者顯示登入畫面,這僅在使用者先前已通過身份驗證的情況下檢查 SSO 時很有用(這與上述值為 check-ssoonLoad 檢查有關)。

  • maxAge - 僅在使用者已通過身份驗證時使用。指定使用者上次通過身份驗證後的最大時間。如果使用者已經通過身份驗證的時間超過 maxAge,則 SSO 會被忽略,並且需要重新進行身份驗證。

  • loginHint - 用於預先填寫登入表單上的使用者名稱/電子郵件欄位。

  • scope - 使用此特定登入的不同值覆蓋在 init 中配置的 scope。

  • idpHint - 用於告訴 Keycloak 跳過顯示登入頁面,並自動重新導向到指定的身份提供者。更多資訊請參閱身份提供者文件

  • acr - 包含有關 acr 宣告的資訊,該宣告將在 claims 參數中傳送至 Keycloak 伺服器。典型用法是用於逐步驗證。使用範例:{ values: ["silver", "gold"], essential: true }。更多詳細資訊請參閱 OpenID Connect 規範和逐步驗證文件

  • acrValues - 產生 acr_values 參數,該參數是指驗證內容類別參考,並允許用戶端宣告所需保證等級需求,例如驗證機制。請參閱OpenID Connect MODRNA 驗證設定檔 1.0 的第 4 節:acr_values 要求值和保證等級

  • action - 如果值為 register,則使用者會被重新導向至註冊頁面。更多詳細資訊請參閱客戶端請求的註冊章節。如果值為 UPDATE_PASSWORD 或其他支援的必要動作,則使用者將被重新導向至重設密碼頁面或其他必要動作頁面。但是,如果使用者未通過身份驗證,則使用者將被傳送到登入頁面,並在身份驗證後重新導向。更多詳細資訊請參閱應用程式起始動作章節

  • locale - 根據 OIDC 1.0 規範的 3.1.2.1 節設定 'ui_locales' 查詢參數。

  • cordovaOptions - 指定傳遞給 Cordova 應用程式內瀏覽器 (如果適用) 的引數。選項 hiddenlocation 不受這些引數的影響。所有可用的選項都定義在https://cordova.dev.org.tw/docs/en/latest/reference/cordova-plugin-inappbrowser/。使用範例:{ zoom: "no", hardwareback: "yes" };

createLoginUrl(options)

傳回一個 Promise,其中包含登入表單的 URL。

Options 是一個可選的物件,支援與函式 login 相同的選項。

logout(options)

重新導向至登出。

選項是一個 Object,其中

  • redirectUri - 指定登出後重新導向到的 URI。

createLogoutUrl(options)

傳回登出使用者的 URL。

選項是一個 Object,其中

  • redirectUri - 指定登出後重新導向到的 URI。

register(options)

重新導向至註冊表單。是使用選項 action = 'register' 登入的快捷方式。

選項與登入方法相同,但 'action' 設定為 'register'

createRegisterUrl(options)

傳回一個 Promise,其中包含註冊頁面的 URL。是使用選項 action = 'register' 建立 createLoginUrl 的快捷方式。

選項與 createLoginUrl 方法相同,但 'action' 設定為 'register'

accountManagement()

重新導向至帳戶主控台。

createAccountUrl(options)

傳回帳戶主控台的 URL。

選項是一個 Object,其中

  • redirectUri - 指定重新導向回應用程式時要重新導向到的 URI。

hasRealmRole(role)

如果 Token 具有給定的領域角色,則傳回 true。

hasResourceRole(role, resource)

如果 Token 具有給定資源的角色,則傳回 true(資源是可選的,如果未指定,則使用 clientId)。

loadUserProfile()

載入使用者設定檔。

傳回一個 Promise,該 Promise 會解析為設定檔。

例如

try {
    const profile = await keycloak.loadUserProfile();
    console.log('Retrieved user profile:', profile);
} catch (error) {
    console.error('Failed to load user profile:', error);
}

isTokenExpired(minValidity)

如果 Token 在過期前剩餘時間少於 minValidity 秒,則傳回 true(minValidity 是可選的,如果未指定,則使用 0)。

updateToken(minValidity)

如果 Token 在 minValidity 秒內過期(minValidity 是可選的,如果未指定,則使用 5),則會重新整理 Token。如果將 -1 作為 minValidity 傳遞,則會強制重新整理 Token。如果啟用會話狀態 iframe,也會檢查會話狀態。

傳回一個 Promise,該 Promise 會解析為一個布林值,指示 Token 是否已重新整理。

例如

try {
    const refreshed = await keycloak.updateToken(5);
    console.log(refreshed ? 'Token was refreshed' : 'Token is still valid');
} catch (error) {
    console.error('Failed to refresh the token:', error);
}

clearToken()

清除身份驗證狀態,包括 Token。如果應用程式偵測到會話已過期,例如在更新 Token 失敗時,此功能會很有用。

呼叫此方法會導致呼叫 onAuthLogout 回呼監聽器。

回呼事件

此適配器支援為特定事件設定回呼監聽器。請記住,必須在呼叫 init() 方法之前設定這些監聽器。

例如

keycloak.onAuthSuccess = () => console.log('Authenticated!');

可用的事件如下

  • onReady(authenticated) - 在初始化適配器時呼叫。

  • onAuthSuccess - 在使用者成功通過身份驗證時呼叫。

  • onAuthError - 如果在身份驗證期間發生錯誤時呼叫。

  • onAuthRefreshSuccess - 在重新整理 Token 時呼叫。

  • onAuthRefreshError - 如果在嘗試重新整理 Token 時發生錯誤時呼叫。

  • onAuthLogout - 在使用者登出時呼叫(僅在啟用會話狀態 iframe 或在 Cordova 模式下才會呼叫)。

  • onTokenExpired - 在存取 Token 過期時呼叫。如果存在重新整理 Token,則可以使用 updateToken 重新整理 Token,或者在不存在重新整理 Token 的情況下(即使用隱式流程),您可以重新導向至登入畫面以取得新的存取 Token。

在此頁面中