npm install keycloak-js
Keycloak 隨附一個名為 keycloak-js
的用戶端 JavaScript 程式庫,可用於保護網頁應用程式的安全。此介面卡也內建支援 Cordova 應用程式。
我們建議您從 NPM 安裝 keycloak-js
套件
npm install keycloak-js
關於使用用戶端應用程式,一個重要的考量是,用戶端必須是公開用戶端,因為沒有安全的方法可以在用戶端應用程式中儲存用戶端憑證。此考量使得確保您為用戶端設定的重新導向 URI 正確且盡可能具體變得非常重要。
若要使用介面卡,請在 Keycloak 管理主控台中為您的應用程式建立用戶端。在「功能設定」頁面上,將用戶端驗證切換為關閉,使該用戶端成為公開用戶端。
您也需要設定 Valid Redirect URIs
和 Web 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-required
或 check-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 不需要任何網路流量。相反地,會透過查看特殊狀態 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'
});
Keycloak 支援使用 Apache Cordova 開發的混合行動應用程式。介面卡有兩種模式:cordova
和 cordova-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'
});
此介面卡需要兩個額外的外掛程式
cordova-plugin-browsertab:允許應用程式在系統的瀏覽器中開啟網頁
cordova-plugin-deeplinks:允許瀏覽器透過特殊 URL 重新導向回您的應用程式
連結至應用程式的技術細節在每個平台上都不同,而且需要特殊設定。如需進一步指示,請參閱 deeplinks 外掛程式文件的 Android 和 iOS 章節。
存在不同種類的連結可用於開啟應用程式
自訂配置,例如 myapp://login
或 android-app://com.example.myapp/https/example.com/login
。
雖然前者較容易設定且往往運作更可靠,但後者因為是獨一無二的,且只有網域擁有者才能註冊,因此提供了額外的安全性。自訂 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 的限制程度而完全停用。轉接器會嘗試偵測此設定並做出相應的反應。
如果在 Keycloak 端和應用程式端都設定了 SSL / TLS 連線,則支援所有功能。例如,Chrome 從 84 版開始會受到影響。
如果轉接器偵測到此類瀏覽器行為,則不支援 Session Status iframe,且會自動停用。這表示轉接器無法使用工作階段 Cookie 來偵測單一登出,而必須完全依賴權杖。因此,當使用者在另一個視窗中登出時,使用轉接器的應用程式將不會登出,直到應用程式嘗試重新整理存取權杖為止。因此,請考慮將存取權杖的存留時間設定為相對較短的時間,以便盡快偵測到登出。如需更多詳細資訊,請參閱工作階段和權杖逾時。
預設情況下,不支援無聲 check-sso
,並且會回退到常規(非無聲)check-sso
。可以透過在傳遞給 init
方法的選項中設定 silentCheckSsoFallback: false
來變更此行為。在這種情況下,如果偵測到瀏覽器的限制性行為,check-sso
將會完全停用。
常規 check-sso
也會受到影響。由於不支援 Session Status iframe,因此在初始化轉接器時,必須額外重新導向至 Keycloak,以檢查使用者的登入狀態。此檢查與使用 iframe 來判斷使用者是否已登入的標準行為不同,且僅在使用者登出時才會執行重新導向。
例如,從 13.1 版開始,Safari 就是一個會受到影響的瀏覽器。
// 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");
如果使用者已驗證,則為 true
,否則為 false
。
可以在對服務的要求中以 Authorization
標頭傳送的 base64 編碼權杖。
剖析為 JavaScript 物件的權杖。
使用者 ID。
base64 編碼的 ID 權杖。
剖析為 JavaScript 物件的 ID 權杖。
與權杖關聯的領域角色。
與權杖關聯的資源角色。
可用於擷取新權杖的 base64 編碼重新整理權杖。
剖析為 JavaScript 物件的重新整理權杖。
瀏覽器時間與 Keycloak 伺服器之間的估計時間差(以秒為單位)。此值僅為估計值,但在判斷權杖是否已過期時已足夠精確。
在 init 中傳遞的回應模式(預設值為 fragment)。
在 init 中傳遞的流程。
可讓您覆寫程式庫處理重新導向和其他與瀏覽器相關的功能的方式。可用選項
「預設」- 程式庫使用瀏覽器 API 進行重新導向(這是預設值)
「cordova」- 程式庫將嘗試使用 InAppBrowser cordova 外掛程式來載入 keycloak 登入/註冊頁面(當程式庫在 cordova 生態系統中運作時,會自動使用此選項)
「cordova-native」- 程式庫嘗試使用手機的系統瀏覽器,透過 BrowserTabs cordova 外掛程式開啟登入和註冊頁面。這需要額外設定才能重新導向回應用程式(請參閱使用 Cordova 的混合應用程式)。
「custom」- 可讓您實作自訂轉接器(僅適用於進階使用案例)
在登入要求時傳送至 Keycloak 的回應類型。這會根據初始化期間使用的流程值來決定,但可以透過設定此值來覆寫。
init(options)
呼叫以初始化轉接器。
選項是一個 Object,其中
useNonce - 新增加密 nonce 以驗證驗證回應是否與要求相符(預設值為 true
)。
onLoad - 指定在載入時要執行的動作。支援的值為 login-required
或 check-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 回應模式。有效值為 query
或 fragment
。預設值為 fragment
,這表示在成功驗證後,Keycloak 會將 OpenID Connect 參數新增至 URL 片段,重新導向至 JavaScript 應用程式。一般而言,這比 query
更安全且更受推薦。
flow - 設定 OpenID Connect 流程。有效值為 standard
、implicit
或 hybrid
。
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-sso
的 onLoad
檢查有關)。
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 應用程式內瀏覽器 (如果適用) 的引數。選項 hidden
和 location
不受這些引數的影響。所有可用的選項都定義在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。