keycloak~認證與校驗的深度總結
主要內容
- 密碼認證
- 授權碼認證
哪個client申請的code,使用哪個client獲取token - 客戶端認證
在kc開通了服務端帳號之后,可通過client_id和client_secret來獲取token,與用戶無關,無刷新token機制 - 自動觸發社區認證
當用戶在社區網站上登錄后,訪問這個地址可自動登錄網站 - 驗證token是否在線
可使用任意client來驗證所有token的在線性 - refresh_token刷新token
哪個client生成的token,就用哪個client去刷新 - 登出/注銷
官方post方式和瀏覽器302方式
密碼認證
- POST /auth/realms/your-realm/protocol/openid-connect/token
- 請求體 x-www-form-urlencoded
grant_type:password
username:test
password:123456
client_secret:ec0fd1c6-68b0-4c39-a9fa-c3be25c8ef01
client_id:democlient
- 響應
{
"access_token": "*.*.*",
"expires_in": 3000,
"refresh_expires_in": 1800,
"refresh_token": "*.*.*",
"token_type": "bearer",
"not-before-policy": 1619512543,
"session_state": "765969ec-94da-4edb-9dcb-e15ea3e0ad3b",
"scope": "roles email profile"
}
授權碼認證
注意的幾點
- code時的redirect_uri和authorization_code的需要是一致的,不一致的錯誤
{
"error": "invalid_grant",
"error_description": "redirect_uri error"
}
- code時的client_id和client_secret和authorization_code的需要是一致的,不一致的錯誤,
這塊我已經修改了源碼,去掉了這個限制
{
"error": "invalid_grant",
"error_description": "Auth error"
} - code的組成
它由3部分組成,中間使用.分割,第一部分是UUID,第二部分是用戶會話ID【session_state】,第三部分是客戶端ID,例如:
5c33f9a2-cbf4-4804-a8ee-e2d076eda2d6.40be5301-f41b-4f0d-97e7-d2074db2801c.ff591897-7654-460e-9c19-8e8f92117768
請求code
- GET /auth/realms/your-realm/protocol/openid-connect/auth
- QUERY
client_id:democlient
scope:openid
response_type:code
client_secret:ec0fd1c6-68b0-4c39-a9fa-c3be25c8ef01
redirect_uri:http://localhost:9090/callback
- 跳轉到kc的登錄頁,完成用戶名和密碼的登錄

- 登錄成功之后,跳回callback刪除,在url參數上帶上了code

請求token
- POST /auth/realms/your-realm/protocol/openid-connect/token
- 請求體 x-www-form-urlencoded
grant_type:authorization_code
code:68058719-add6-4b40-ab96-8e71af03827a.7a31b1a9-c3e8-46d4-b8cc-345012fcf4a2.25e52f60-5991-43dd-9108-873f60af385d
client_id:democlient
client_secret:ec0fd1c6-68b0-4c39-a9fa-c3be25c8ef01
scope:openid
redirect_uri:http://localhost:9090/callback
- 響應
{
"access_token": "*.*.*",
"expires_in": 3000,
"refresh_expires_in": 1800,
"refresh_token": "*.*.*",
"token_type": "bearer",
"id_token": "*.*.*",
"not-before-policy": 1619660302,
"session_state": "14812f50-b9f7-4cee-be56-bf9bef5c961a",
"scope": "openid roles email profile"
}
客戶端認證
客戶端認證,與用戶無關,主要保證向keycloak發起的請求,來自合法的client即可(由keycloak頒發的client)
- POST /auth/realms/your-realm/protocol/openid-connect/token
- 請求
x-www-form-urlencoded - 參數
grant_type:client_credentials
client_secret:912ecc47-60b1-4dd4-8f62-c7745c293cab
client_id:kce
- 注意,需要在keycloak客戶端配置開啟
服務賬號

- 如果沒有開啟
服務賬號,將出現下面異常
{
"error": "unauthorized_client",
"error_description": "Client not enabled to retrieve service account"
}
自動觸發社區認證
carsi中出現的東西,院校希望直接通過固定的uri實現社區登錄,故開發這個功能
- 地址:GET https://kc.democlient.com/auth/realms/your-realm/protocol/openid-connect/auth?scope=openid&response_type=code&client_id=carsi-auto&redirect_uri=https://www.baidu.com
- 首先,需要在配置
Authentication Flows中的brower中的社區登錄的有限級最高,我們可以復制一個brower認證流,在新流上修改,用戶密碼認證步驟關閉,也可以刪除

- 這個里的重定向認證使用的認證流是carsi

- 其次,需要新添加客戶端,專門用來發送社區自動認證請求的,如
carsi-auto,或者配置客戶端的自定義認證方式

- 最后,測試一下,你可以看到,通過這個地址,可以喚起社區登錄,最后回調到我們OIDC認證上來

驗證token是否在線
是否觸發了keycloak的logout接口,如果觸發了,那token將被刪除,在線狀態active為false,如果不希望提供client_secret參數,也可以通過
/auth/realms/your-realm/protocol/openid-connect/userinfo接口來判斷token是否有效,httpcode為401表示token失效.
- 使用場景:a客戶端在kc申請的token,可以在b客戶端調用kc的接口去校驗它的合法性
- POST /auth/realms/your-realm/protocol/openid-connect/token/introspect
- 請求體 x-www-form-urlencoded
token:*.*.*
client_id:democlient
client_secret:ec0fd1c6-68b0-4c39-a9fa-c3be25c8ef01
- 響應,狀態碼都是200,如果json體中active為false,表示已經離線
{
"active": false
}
refresh_token刷新token
注意,刷新token與客戶端有關,自己客戶端生產的access_token,只能由自己客戶端去refresh_token刷新
- POST /auth/realms/your-realm/protocol/openid-connect/token
grant_type:refresh_token
refresh_token:*.*.*
client_id:democlient
client_secret:ec0fd1c6-68b0-4c39-a9fa-c3be25c8ef01
- 響應
新的token對象
{
"access_token": "*.*.*",
"expires_in": 3000,
"refresh_expires_in": 1800,
"refresh_token": "*.*.*",
"token_type": "bearer",
"not-before-policy": 1621497420,
"session_state": "405d25b0-5128-45ae-9934-953eecb79894",
"scope": "roles profile"
}
登出/注銷
KC的登出是屬于會話的登出,通過這個會話產生的所有token(一個會話可能對應多個不同client的token)都將會退出
一般地,如果是前后不分享項目,應該還會清除自己網站的session會話,然后再去調用KC的接口
- POST /auth/realms/your-realm/protocol/openid-connect/logout
- 請求體 x-www-form-urlencoded
refresh_token:*.*.*
client_id:democlient
client_secret:ec0fd1c6-68b0-4c39-a9fa-c3be25c8ef01
- 響應
HttpCode為200或者204表示操作成功
- 瀏覽器端可通過這個接口來實現
302瀏覽器跳轉方式的登出
GET /auth/realms/your-realm/sms/remove-sessions?redirect_uri={redirect_uri}
登出后,KC會跳轉到redirectUri的頁面
浙公網安備 33010602011771號