keycloak~關於授權碼認證中的scope的實踐

张占岭發表於2024-09-25

前言

1. scope 引數的作用

  • 定義許可權scope 用於宣告請求訪問的資源和許可權。常見的值包括 openidprofileemail 等。
  • 影響返回的資料:如果你在授權請求中指定了某些 scope,在後續的 token 請求中,Keycloak 會根據這些 scope 返回相應的資訊。
  • openid用於指示請求者希望使用 OpenID Connect 進行身份驗證
  • 獲取 ID Token:當你在授權請求中包含 openid 時,Keycloak 會返回一個 ID Token,包含使用者的身份資訊,反之,scope裡不加openid,則不會生成ID Token這個欄位。

2. 在不同階段使用 scope

  • 授權請求階段 (/protocol/openid-connect/auth):

    • 可以傳遞 scope 引數,以便在使用者同意授權時,明確所請求的許可權。
  • 令牌請求階段 (/protocol/openid-connect/token):

    • 也可以在此階段傳遞 scope,但通常情況下,如果在授權請求中已指定 scope,則不需要在此再次指定;
    • 在授權中指定了scope,這裡再指定是無效的,以授權中指定的值為準

3. 示例

以下是一個獲取授權碼的請求示例:

GET /auth/realms/{realm}/protocol/openid-connect/auth?
response_type=code&
client_id={client_id}&
redirect_uri={redirect_uri}&
scope=openid profile

4. 總結

  • 建議:雖然 scope 在授權請求中是可選的,但為了確保獲得正確的許可權和資料,建議在請求中包含 scope 引數。
  • 注意:在實際開發中,根據你的應用需求合理配置 scope 是非常重要的。

實踐

oauth2授權碼認證的過程

1. 配置客戶端及scope模板

  • 預設模板,無論應用是否傳scope,預設模板裡的許可權都會被啟用
  • 可選模板,由使用者自己選擇,透過scope來體現,它會追加到預設模板後面

2. 獲取授權碼

  • scope中體現了獲取使用者的email,這一步是由使用者自己選擇的公開的資訊
  • 地址:/auth/realms/{realm}/protocol/openid-connect/auth?client_id=dahengshuju&scope=profile email&redirect_uri=http://www.baidu.com&response_type=code

3. 表單認證

  • 提示使用者輸入賬號密碼進行登入
  • 登入成功後,重定向到來源頁,帶上code碼
  • code授權碼使用一次後,立即過期

4. 獲取token

  • 透過步驟3,獲取到的code,它透過scope來限制授權的範圍【即token和獲取使用者資訊中包含的欄位集合】
  • 步驟2指定了scope,這一步再指定scope是無效的,二選一即可
  • 地址:/auth/realms/{realm}/protocol/openid-connect/token
  • 請求表型別:x-www-form-urlencoded
  • 請求引數
grant_type:authorization_code
code:3be438fe-8651-4a84-8141-976b76e671e1.75cab95f-a1ec-4b9b-9a6e-8f1ecb651cd6.61d819de-33e4-4006-ae66-dd7609ea2d3e
client_id:dahengshuju
client_secret:9e3de70f-d5cd-4d11-a8aa-85fd3af13265
scope:profile
  • 這是scope為profile email的token
{
    "exp": 1727233162,
    "iat": 1727231362,
    "auth_time": 1727229121,
    "jti": "bb296d9d-d521-45b1-aab9-8cb6bea0ddc3",
    "iss": "https://xx.xx.com/auth/realms/xx",
    "sub": "347c9e9e-076c-45e3-be74-c482fffcc6e5",
    "typ": "Bearer",
    "azp": "dahengshuju",
    "session_state": "75cab95f-a1ec-4b9b-9a6e-8f1ecb651cd6",
    "acr": "0",
    "scope": "email profile",
    "email_verified": false,
    "preferred_username": "test",
    "locale": "zh-CN",
    "email": "bfyxzls@gmail.com"
}
  • 這是scope為profile的token,裡面是沒有email資訊的
{
    "exp": 1727233521,
    "iat": 1727231721,
    "auth_time": 1727229121,
    "jti": "f7de8ad9-7558-4f4a-8761-8724f685febb",
    "iss": "https://xx.xx.com/auth/realms/xx",
    "sub": "347c9e9e-076c-45e3-be74-c482fffcc6e5",
    "typ": "Bearer",
    "azp": "dahengshuju",
    "session_state": "75cab95f-a1ec-4b9b-9a6e-8f1ecb651cd6",
    "acr": "0",
    "scope": "profile",
    "preferred_username": "test",
    "locale": "zh-CN"
}

5. 透過access_token獲取使用者資訊

  • 使用者資訊主要是對token中的內容進行解析
  • 地址:/auth/realms/{realm}/protocol/openid-connect/userinfo
  • 請求頭:Authorization: Bearer
{
    "sub": "347c9e9e-076c-45e3-be74-c482fffcc6e5",
    "email_verified": false,
    "preferred_username": "test",
    "locale": "zh-CN",
    "email": "xxx@gmail.com"
}

相關文章