Keycloak 授權用戶端

使用 Keycloak 授權用戶端管理和檢查權限

根據您的需求,資源伺服器應該能夠遠端管理資源,甚至以程式化的方式檢查權限。如果您使用 Java,可以使用授權用戶端 API 存取 Keycloak 授權服務。

它適用於想要存取伺服器提供的不同端點(例如 Token 端點、資源和權限管理端點)的資源伺服器。

Maven 相依性

<dependencies>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-authz-client</artifactId>
        <version>26.0.2</version>
    </dependency>
</dependencies>

設定

用戶端設定定義在 keycloak.json 檔案中,如下所示

{
  "realm": "hello-world-authz",
  "auth-server-url" : "https://127.0.0.1:8080",
  "resource" : "hello-world-authz-service",
  "credentials": {
    "secret": "secret"
  }
}
  • realm(必要)

    領域的名稱。

  • auth-server-url(必要)

    Keycloak 伺服器的基本 URL。所有其他 Keycloak 頁面和 REST 服務端點都由此衍生而來。它通常採用 https://host:port 的形式。

  • resource(必要)

    應用程式的 client-id。每個應用程式都有一個 client-id,用於識別應用程式。

  • credentials(必要)

    指定應用程式的憑證。這是一個物件表示法,其中鍵是憑證類型,值是憑證類型的值。詳細資訊請參閱專門的章節

設定檔通常位於應用程式的類別路徑中,這是用戶端嘗試尋找 keycloak.json 檔案的預設位置。

建立授權用戶端

假設您的類別路徑中有 keycloak.json 檔案,您可以建立一個新的 AuthzClient 實例,如下所示

// create a new instance based on the configuration defined in a keycloak.json located in your classpath
AuthzClient authzClient = AuthzClient.create();

取得使用者權限

以下範例說明如何取得使用者權限

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// create an authorization request
AuthorizationRequest request = new AuthorizationRequest();

// send the entitlement request to the server in order to
// obtain an RPT with all permissions granted to the user
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request);
String rpt = response.getToken();

System.out.println("You got an RPT: " + rpt);

// now you can use the RPT to access protected resources on the resource server

以下範例說明如何取得一組或多個資源的使用者權限

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// create an authorization request
AuthorizationRequest request = new AuthorizationRequest();

// add permissions to the request based on the resources and scopes you want to check access
request.addPermission("Default Resource");

// send the entitlement request to the server in order to
// obtain an RPT with permissions for a single resource
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request);
String rpt = response.getToken();

System.out.println("You got an RPT: " + rpt);

// now you can use the RPT to access protected resources on the resource server

使用保護 API 建立資源

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// create a new resource representation with the information we want
ResourceRepresentation newResource = new ResourceRepresentation();

newResource.setName("New Resource");
newResource.setType("urn:hello-world-authz:resources:example");

newResource.addScope(new ScopeRepresentation("urn:hello-world-authz:scopes:view"));

ProtectedResource resourceClient = authzClient.protection().resource();
ResourceRepresentation existingResource = resourceClient.findByName(newResource.getName());

if (existingResource != null) {
    resourceClient.delete(existingResource.getId());
}

// create the resource on the server
ResourceRepresentation response = resourceClient.create(newResource);
String resourceId = response.getId();

// query the resource using its newly generated id
ResourceRepresentation resource = resourceClient.findById(resourceId);

System.out.println(resource);

內省 RPT

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// send the authorization request to the server in order to
// obtain an RPT with all permissions granted to the user
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize();
String rpt = response.getToken();

// introspect the token
TokenIntrospectionResponse requestingPartyToken = authzClient.protection().introspectRequestingPartyToken(rpt);

System.out.println("Token status is: " + requestingPartyToken.getActive());
System.out.println("Permissions granted by the server: ");

for (Permission granted : requestingPartyToken.getPermissions()) {
    System.out.println(granted);
}

用戶端驗證

當授權用戶端需要傳送後端通道請求時,它需要向 Keycloak 伺服器驗證。預設情況下,有三種方法可以驗證用戶端:用戶端 ID 和用戶端密碼、使用簽署的 JWT 進行用戶端驗證,或使用用戶端密碼使用簽署的 JWT 進行用戶端驗證。

用戶端 ID 和用戶端密碼

這是 OAuth2 規範中描述的傳統方法。用戶端有一個密碼,需要讓用戶端和 Keycloak 伺服器都知道。您可以在 Keycloak 管理主控台中為特定用戶端產生密碼,然後將此密碼貼到應用程式端的 keycloak.json 檔案中

"credentials": {
    "secret": "19666a4f-32dd-4049-b082-684c74115f28"
}

使用簽署的 JWT 進行用戶端驗證

這基於 RFC7523 規範。它的運作方式如下

  • 用戶端必須具有私鑰和憑證。對於授權用戶端,這可以通過傳統的 keystore 檔案取得,該檔案可以在用戶端應用程式的類別路徑中,或在檔案系統的某個位置取得。

  • 在驗證期間,用戶端會產生一個 JWT 權杖,並使用其私鑰簽署該權杖,並在特定請求中的 client_assertion 參數中傳送給 Keycloak。

  • Keycloak 必須具有用戶端的公鑰或憑證,以便它可以驗證 JWT 上的簽名。在 Keycloak 中,您需要為您的用戶端設定用戶端憑證。首先,在管理主控台中的 憑證 索引標籤中,選擇 簽署的 JWT 作為驗證用戶端的方法。然後,您可以在 金鑰 索引標籤中選擇以下其中一種方法

    • 設定 JWKS URL,Keycloak 可以從該 URL 下載用戶端的公鑰。此選項是最靈活的,因為用戶端可以隨時輪換其金鑰,而 Keycloak 總是根據需要下載新金鑰,而無需變更設定。換句話說,當 Keycloak 看到由未知的 kid(金鑰 ID)簽署的權杖時,它會下載新金鑰。但是,您需要注意將公鑰以 JWKS 格式公開到某處,以供伺服器使用。

    • 上傳用戶端的公鑰或憑證,可以採用 PEM 格式、JWK 格式或從金鑰儲存區上傳。使用此選項時,公鑰是硬式編碼的,當用戶端產生新的金鑰對時必須變更。如果您沒有自己的金鑰儲存區,甚至可以從 Keycloak 管理主控台產生您自己的金鑰儲存區。使用授權用戶端時,此選項最容易。

若要設定此方法,您需要在 keycloak.json 檔案中編寫如下程式碼

"credentials": {
  "jwt": {
    "client-keystore-file": "classpath:keystore-client.jks",
    "client-keystore-type": "JKS",
    "client-keystore-password": "storepass",
    "client-key-password": "keypass",
    "client-key-alias": "clientkey",
    "token-expiration": 10
  }
}

透過此設定,金鑰儲存區檔案 keystore-client.jks 必須可在使用授權用戶端的應用程式的類別路徑中取得。如果您不使用字首 classpath:,您可以指向執行用戶端應用程式的檔案系統上的任何檔案。

使用用戶端密碼使用簽署的 JWT 進行用戶端驗證

這與使用簽署的 JWT 進行用戶端驗證相同,只是使用了用戶端密碼而不是私鑰和憑證。

用戶端有一個密碼,需要讓使用授權用戶端的應用程式和 Keycloak 伺服器都知道。在管理主控台中的 憑證 索引標籤中,選擇 使用用戶端密碼簽署的 JWT 作為驗證用戶端的方法,然後將此密碼貼到應用程式端的 keycloak.json 檔案中

"credentials": {
  "secret-jwt": {
    "secret": "19666a4f-32dd-4049-b082-684c74115f28",
    "algorithm": "HS512"
  }
}

「algorithm」欄位指定使用用戶端密碼簽署的 JWT 的演算法。它必須是以下值之一:HS256、HS384 和 HS512。詳情請參閱JSON Web 演算法 (JWA)

此「algorithm」欄位是可選的;如果 keycloak.json 檔案中不存在「algorithm」欄位,則會自動套用 HS256。

新增您自己的用戶端驗證方法

您也可以新增您自己的用戶端驗證方法。您需要同時實作用戶端和伺服器端提供者。有關詳細資訊,請參閱 伺服器開發人員指南中的 驗證 SPI 章節。

在此頁面