Identity Server 4 - Hybrid Flow - 保護API資源

solenovex發表於2018-07-07

這個系列文章介紹的是Identity Server 4 的 Hybrid Flow, 前兩篇文章介紹瞭如何保護MVC客戶端, 本文介紹如何保護API資源.

保護MVC客戶端的文章: https://www.cnblogs.com/cgzl/p/9253667.html,  https://www.cnblogs.com/cgzl/p/9268371.html

相關程式碼: https://github.com/solenovex/Identity-Server-4-Tutorial-Code 裡面03那部分.

 

回顧 Hybrid Flow

回顧一下該專案使用的流程

圖裡有IDP (Identity Provider, 我例子裡是用Identity Server 4構建的專案)和客戶端(我的例子裡是MVC客戶端).

在上面流程走完之後, MVC客戶端獲得了Access Token, MVC客戶端驗證Access Token併成功後, 就可以使用Access Token來訪問被保護的API資源了, 而Access Token會在被保護的API那裡再次進行驗證.

 

保護API

首先在IDP裡配置一個返回ApiResoruce的方法:

和IdentityResource類似, ApiResource就是與API相關的scopes.

 

在Client配置那裡, 把這個ApiResource的名字新增到允許的scopes裡:

 

最後在IDP的startup裡, 註冊ApiResources:

 

現在來到MVC客戶端這裡, 需要把上面的scope新增上:

 

最後來到API專案, 首先確保使用HTTPS:

 

API專案還需要安裝IdentityServer4.AccessTokenValidation這個包, 可以通過Nuget安裝.

安裝後, 還需要進行配置 (官方文件: https://identityserver4.readthedocs.io/en/release/quickstarts/1_client_credentials.html#adding-an-api): 

其中IdentityServerAuthenticationDefaults.AuthenticationScheme 就是 “Bearer” 的意思, 這裡使用的就是這個方案.

AddIdentityServerAuthentication()方法註冊了Access Token 驗證的處理者. 裡面Authority就是IDP的URI, ApiName就是IDP裡配置的API的名字.

 

在Startup的Configure方法裡, 還需要把它新增到管道:

要確保它在UseMVC之前呼叫.

 

我在API專案裡使用過濾器為所有的Controller都加上了授權過濾:

當然也可以在具體的Controller或Action級寫上這個:

無論如何現在訪問Country資源是需要授權的.

 

回到MVC客戶端, 在Home的Contact Action裡呼叫CountryAPI資源:

 

 

下面測試一下未使用Access Token訪問被保護的Country資源的情況, 重新操作可以看到使用者同意授權頁面出現了剛才配置的API資源名:

在訪問Contact頁面的時候, 提示未授權:

 

那就用之前介紹過的方法來獲取Access Token並設定Authorization Header為 “Bearer [AccessToken]” 即可:

 

再修改一下Contact頁面, 顯示Access Token:

 

重新操作, 就可以看到Country資源資料了:

 

Access Token

去jwt.io對Access Token進行解碼:

看一下aud (audience, 觀眾) 這個屬性, 它有兩個值, 第一個是指IDP那邊對資源 (呼叫使用者資訊端點), 第二個就是指API那個專案.

這個屬性說明這個access token是為它們倆準備的.

而scope裡面的“restapi”就是aud裡面的“restapi”, 所以這個token允許被用來訪問我們的“restapi”.

而scope裡面的“profile”等scopes是對應另一個aud的值, 這些scopes來自IDP那裡.

 

現在Access Token有這些claims, API也就能得到這些claims, 但是有時API還需要使用者身份相關的claims.

修改IDP的ApiResource配置即可:

 

再次操作後, 檢視token, 就可以看到我剛剛新增的那兩個claim了:

 

而role這個claim, 在API裡是可以被識別成角色的, 如果我在API的Action上設定許可權如下:

那麼, Nick這個使用者就可以得到Country資料, 而Dave則會顯示403 Forbidden:

 

相關文章