簡體   English   中英

Keycloak:使用 keycloak-admin 為用戶生成訪問令牌

[英]Keycloak: Generate access token for a user with keycloak-admin

我必須將遺留身份驗證系統移至 Keycloak,並且我無法更改客戶端上的實際工作流程。 因此,我需要為我的 api(在 node.js 中)提供一個用戶創建和登錄系統,該系統又代表用戶從 Keycloak 創建和獲取訪問令牌。

我能夠創建一個用戶,但我一直無法找到為該用戶生成訪問令牌的方法。 我發現的唯一解決方法是創建一個用戶並設置一個隨機密碼,然后要求授予提供用戶名和密碼的用戶,但這意味着我必須在我這邊存儲密碼,這正是我想移動的原因到鑰匙斗篷。

const KcAdminClient   = require('keycloak-admin').default;
const Keycloak        = require('keycloak-connect');

const _keycloakAdmin = new KcAdminClient({
  baseUrl: process.env.KEYCLOAK_SERVER_AUTH_URL,
  realm: process.env.KEYCLOAK_REALM
});
await _keycloakAdmin.auth({
  realm: process.env.KEYCLOAK_REALM,
  username: process.env.KEYCLOAK_USER,
  password: process.env.KEYCLOAK_PASSWORD,
  grantType: 'password',
  clientId: process.env.KEYCLOAK_CLIENT_ID,
});

//Create a user and set password 
const newUser = await _keycloakAdmin.users.create({
  realm: process.env.KEYCLOAK_REALM,
  username: 'something',
  email: 'someone@domain.com',
  firstName: 'Some',
  lastName: 'One',
  emailVerified: true,
  enabled: true,
});

await _keycloakAdmin.users.resetPassword({
    realm: process.env.KEYCLOAK_REALM,
    id: newUser.id,
    credential: {
        temporary: false,
        type: 'password',
        value: 'randompassword'
    }
});

//generate a token for the user
const _keycloak = new Keycloak({}, {
  clientId: process.env.KEYCLOAK_CLIENT_ID,
  serverUrl: process.env.KEYCLOAK_SERVER_AUTH_URL,
  realm: process.env.KEYCLOAK_REALM,
  credentials: {
      secret: process.env.KEYCLOAK_CLIENT_SECRET
  }
});
const grant = await _keycloak.grantManager.obtainDirectly('something', 'randompassword');
const access_token = grant.access_token.token;

我不敢相信不存在更優雅的方式來做到這一點,所以我認為我在我的 Keycloak 客戶端配置和理解一些基本概念和命名約定方面缺少一些基本的東西。 我會期待類似的東西

await _keycloakAdmin.users.generateAccessToken(userId, realm, clientId, ...)

但我找不到它。 我只在 SO 上找到這個未回答的問題: Keycloak:REST API call to get access token of a user through admin username and password

該解決方案非常復雜,需要(在撰寫本文時)激活名為 Token Exchange 的 Keycloak 的“預覽”功能。 該過程在https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange中進行了描述,對於我的具體情況,我遵循了https://www.keycloak.org/docs/中的說明latest/securing_apps/index.html#internal-token-to-internal-token-exchange

首先,您需要啟用令牌交換功能,在運行 Keycloak 時將開關-Dkeycloak.profile=preview添加到JAVA_OPTS 要檢查 Keycloak 是否加載了預覽功能,請在配置文件部分下的/auth/admin/master/console/#/server-info查看您的服務器信息: Keycloak 服務器信息配置文件

令牌交換的想法是,您為 realm 的管理員獲取令牌,然后將其交換為“普通”用戶的令牌。 為此,您必須為您的 Keycloak realm 創建(如果您還沒有)兩個不同的客戶端:第一個是管理員用來獲取令牌的“起始客戶端”,第二個是“目標客戶端”您想要“普通”用戶的令牌。

之后,您需要為您的 realm 創建一個管理員用戶。您可以按照 Keycloak 中的說明進行操作 - 在Realm 中創建管理員用戶

然后您需要使目標客戶端能夠接受令牌交換。 您應該仔細遵循https 中的說明://www.keycloak.org/docs/latest/securing_apps/index.html#_client_to_client_permission這是一個分為兩步的過程:創建指定哪些“起始客戶端”可以交換令牌的客戶端策略然后為目標客戶端啟用權限並將剛剛創建的策略附加到token-exchange權限:

附加到目標客戶端的令牌交換權限的策略

完成 Keycloak 的設置后,您實際上可以發出兩個調用,首先為 realm 的管理員獲取令牌,然后為具有特定 userId 的用戶獲取令牌。

獲取管理員令牌

curl --location --request POST '<your_url>/auth/realms/<your_realm>/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=<your_starting_client>' \
--data-urlencode 'username=<your_admin_username>' \
--data-urlencode 'password=<your_admin_password>' \
--data-urlencode 'realm=<your_realm>' \
--data-urlencode 'scope=openid'

將管理員令牌交換為“普通”用戶令牌

curl --location --request POST '<your_url>/auth/realms/<your_realm>/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'client_id=<your_starting_client>' \
--data-urlencode 'subject_token=<your_admin_token>' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:refresh_token' \
--data-urlencode 'audience=<your_target_client>' \
--data-urlencode 'requested_subject=<your_target_user_id>'

根據客戶端的配置,您最終可能必須在第二次調用中指定client_secret

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM