實戰OAUTH 2.0授權機制

OAUTH 2.0簡介

OAUTH 2.0是現在業界流行的認證授權方式,用戶可以授權應用程序在不提供用戶的密碼的場景下,可以遵循OAUTH的規範來申請獲取訪問服務器的用戶相關資源的權限。OAUTH 2.0的規範和流程還是比較難理解的,因此我用Keycloak來實際演示一下如何按照OAUTH 2.0的協議來進行授權。

OAUTH 2.0有以下四種授權方式:

Authorization Code

這種方式是最安全的,應用程序在用戶登錄認證成功後,授權服務器會返回一個code,應用程序需要用client_id和client secert以及這個code來換取一個token,這個token是由授權服務器進行簽名後授予的一個憑證,裏面包括了授權這個token的擁有者可以獲得哪些資源的訪問能力。應用程序拿到這個token後再和服務提供商請求獲取服務。服務提供商拿到token進行校驗,如果是授權服務器簽發的,則授權通過。這種方式適合應用程序部署在服務器端的方式(server side application),因爲可以在服務器端安全的保存client secret,即使code被第三方獲取,也不能直接通過code來獲得token。

Implicit

這種方式適合應用程序運行在客戶端設備的方式(client side application),例如運行在客戶手機的程序,或者web的java script等。因爲在客戶端設備無法安全的保存client secret,這種方式是直接申請獲取token,而不是通過code的方式來間接獲取。

Password

這種方式是直接以用戶的用戶名和密碼來獲取授權的token。這種方式只適合在用戶高度信任應用程序的場景下,實際很少使用

Client Credential

這種方式是資源服務器是應用程序的一個後端模塊,客戶端向認證服務器提供client id和client secret來驗證身份來獲取令牌。

OAUTH 2.0演示

下面結合Keycloak來介紹一下authorization code, implicit, client credential這三種方式的認證授權流程。

  1. 進入keycloak管理界面,新建一個Realm, 命名爲test
  2. 在test realm裏面,在roles裏面新建一個role,命名爲API-VehicleData,代表後端提供了一個叫做vehicledata的API,可以讀取用戶的車輛信息。
  3. 在test realm裏面,在client scope裏面新建一個scope,命名爲Scope-VehicleData,這個將出現在用戶Consent的界面,代表用戶是否同意應用程序獲取其車輛數據。
  4. 在test realm裏面,新建一個client,命名爲My-App,這個代表了一個應用程序。在setting裏面access type設置爲confidential,打開Implicit Flow,valid redirect URI填入一個接收code或者token的地址,這裏我先填入一個假地址例如http://www.example.com。在credential裏面可以獲取這個client的secret。在client scopes裏面把剛纔創建的API-VehicleData的role賦予到Assigned Default Client Scopes。在Scope裏面設置Full Scope Allowed爲off,然後加入剛纔創建的Scope-VehicleData到assigned scope。
  5. 在test realm裏面,新建一個user alice,這個用戶將調用My-App來訪問服務器端的vehicledata API來獲取自己的車輛信息。

Keycloak的設置完成後,在test realm的realm setting->General->Endpoint->Openid endpoint configuration可以看到keycloak提供的各種endpoint,我們就可以調用keycloak的服務來進行演示了。

Authoriazion Code演示

  1. 獲取code:在瀏覽器中打開http://192.168.1.107:8080/auth/realms/test/protocol/openid-connect/auth?response_type=code&client_id=My-App&redirect_uri=http://www.example.com, 用alice的用戶名登錄後,會有一個consent的頁面,詢問是否授權My-App使用Scope-VehicleData這個特權,授權完成後可以見到瀏覽器被重定向到了example.com,參數裏面帶了一個code,例如http://www.example.com/?session_state=fa5b9adb-a71b-4cc6-bcc7-5b1de2f899aa&code=c820ab0c-63db-4062-a236-87b2ee93890f.c47c9db3-f783-42b4-aeea-f4b88e4d58d7.8bf296ce-e2de-45bf-bce3-b377a5c05222
  2. 獲取token:通過以下命令curl -d "client_secret=5160e3c2-9a02-4a59-aaf8-6f7af3aef1f9" -d "client_id=My-App" -d "grant_type=authorization_code" -d "code=c820ab0c-63db-4062-a236-87b2ee93890f.c47c9db3-f783-42b4-aeea-f4b88e4d58d7.8bf296ce-e2de-45bf-bce3-b377a5c05222" -d "redirect_uri=http://www.example.com" "http://192.168.1.107:8080/auth/realms/test/protocol/openid-connect/token", keycloak會返回一段json數據,其中的access_token是由3段組成,每段之間用.來分隔,第二段包括了賦予這個client的信息,我們可以用base64解碼後查看內容
  3. 解碼後的token第二段內容如下:{"jti":"41293d3c-f04f-40f7-84d5-ca8007f8f02b","exp":1581604011,"nbf":0,"iat":1581603711,"iss":"http://192.168.1.107:8080/auth/realms/test","sub":"43808ffc-2462-46cc-b342-7fde39289e9f","typ":"Bearer","azp":"My-App","auth_time":1581603659,"session_state":"c47c9db3-f783-42b4-aeea-f4b88e4d58d7","acr":"1","scope":"Scope-VehicleData"}, 可以看到有token過期時間,還有Scope-VehicleData, 以及sub中的用戶alice的id
  4. My-App可以把這個token加到bearer中對後端的API進行訪問,後端API可以通過Keycloak驗證這個token,查詢這個My-App是否具有API-VehicleData來調用這個API,並且根據token的第二段的內容來判斷My-App是否有權限讀取alice的車輛信息。

Implicit演示

  1. 獲取token: 在瀏覽器中打開http://192.168.1.107:8080/auth/realms/test/protocol/openid-connect/auth?response_type=token&client_id=My-App&redirect_uri=http://www.example.com, 重定向後的URL裏面帶了token
  2. token的內容和校驗方法如authorization code

client secret演示

  1. 在clients裏面開啓service account,然後執行命令curl -d "client_secret=5160e3c2-9a02-4a59-aaf8-6f7af3aef1f9" -d "client_id=My-App" -d "grant_type=client_credentials" "http://192.168.1.107:8080/auth/realms/test/protocol/openid-connect/token"

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章