[譯]移動API安全終極指南

debug666發表於2017-11-09

文章主要講了移動api呼叫的授權和驗證問題,原文連結:The Ultimate Guide to Mobile API Security

移動API的使用是Stack Overflow和 Stormpath支援頻道上經常出現的話題。這是一個已經被解決的問題,但是需要大量必要的知識和充足的理解才能很好地實現。

這篇文章能夠讓你瞭解到有關於在移動裝置上安全的呼叫Restful API的一切內容,無論你是在構建一個需要訪問Restful API的移動app,還是正在寫Restful API並且打算和移動app開發者進行互動。

我的目標不僅僅是解釋如何確保移動開發者能夠安全呼叫你的Restful API,同時還解釋整個憑證從開始到結束的交換過程,以及如何從安全漏洞中恢復等等。

移動API安全問題

在我們投身去探究如何確保移動開發者能夠安全呼叫Restful API之前,讓我們先討論一下什麼使得移動認證有別於傳統的API認證。

API認證最基本的形式就是一般為我們所知的HTTP Basic Authentication

對於API服務開發者和使用它的人來說,它的工作方式是非常簡單的:

· 開發者會獲取到一個API key(一般是ID和Secret)。這個API key一般像這樣:3bb743bbd45d4eb8ae31e16b9f83c9ba:ffb7d6369eb84580ad2e52ca3fc06c9d。

· 開發者有責任將API key存放在一個安全的地方,沒有人可以得到它。

· 開發者發起API請求時,需要把API key放到HTTP Authorization header中,同時帶有關鍵詞Basic(也就是使用者名稱和密碼都使用base64加密)。下面展示了開發者在呼叫API時如何指定API key進行認證,使用命令列工具cURL。

$ curl --user 3bb743bbd45d4eb8ae31e16b9f83c9ba:ffb7d6369eb84580ad2e52ca3fc06c9d https://api.example.com/v1/test

cURL工具可以將獲取到的API證書用base64加密,然後建立一個HTTP Authorization hearder,如下所示:Basic M2JiNzQzYmJkNDVkNGViOGFlMzFlMTZiOWY4M2M5YmE6ZmZiN2Q2MzY5ZWI4NDU4MGFkMmU1MmNhM2ZjMDZjOWQ=.。而API伺服器將會從HTTP Authorization hearder中獲取字串,然後用base64解密,獲得ID和Secret,驗證通過後再處理相應的API請求。

HTTP Basic Authentication雖然簡單,但是很好用。開發者在呼叫API時附帶API key可以很好地與API伺服器進行驗證。

但是,由於移動app無法安全儲存API祕鑰,使得HTTP Basic Authentication並不是一個很好的選擇。同時,HTTP Basic Authentication要求在每次請求時使用原始的API keys,這就導致了keys會被長期使用,這是不安全的。

因此在大多數情況下,這種驗證方式是不切實際的,因為無法安全的將API keys嵌入到分配給許多使用者的移動app中。

比如說,你將API keys嵌入到你所構建的移動app中,然而一個精明的使用者能夠對你app進行反向工程,獲取到keys,從而濫用你的API服務。

這就是為什麼在不可信的環境中,HTTP Basic Authentication不是一個最好的選擇,例如web瀏覽器和移動app。

注意:和其他所有認證協議一樣,HTTP Basic Authentication必須在SSL之上使用。

為移動安全引入OAuth2.0

在此之前你可能聽說過OAuth,並且在爭論它是什麼和它並沒有足夠的好。那麼讓我們明確:OAuth2是一個優秀的協議,在不受信任的裝置中用於保護API服務的安全。它通過一種我們稱之為token的認證方式來對移動使用者進行認證。

下面我們從使用者的角度OAuth2 token認證的工作方式。

1. 使用者開啟移動app,輸入賬號和密碼。

2. 移動app傳送一個帶有使用者的使用者名稱和密碼的POST請求到API伺服器,伺服器進行驗證,成功後返回一個code。

3. 移動app通過code向認證伺服器傳送請求,認證成功後為使用者生成一個一段時間後就會過期的access token。

4. 將access token儲存在移動裝置本地,就像一個能夠訪問API服務的API key一樣。

5. 一旦access token過期就不再工作,需要再提示使用者輸入使用者名稱密碼,重複1的步驟。

之所以說OAuth2在保障APIs安全上是極好的,是因為我們不需要在一個不安全的環境中長期儲存API keys,取而代之的是生成一個臨時的access tokens。這可以抵禦一些潛在的攻擊。

現在,當您的API服務生成您的移動應用程式需要的Oauth2 token時,您當然需要將其儲存在您的移動應用程式中。

但是存在哪裡?!

token儲存的位置取決於你所處的開發平臺。如果你開發的是一個android app,你會將access tokens儲存在SharedPreferences中,如果你的IOS開發者,你將會將access tokens存在Keychain中。

如果你仍然存在疑問,下面這兩個Stack Overflow的posts可能會非常有用,它詳細闡述瞭如何在移動app中儲存access token。

· Where should I store access tokens on Android?

· Where should I store access tokens on iOS?

現在你應該對OAuth2有所瞭解,為什麼要使用它,以及它的工作原理。

Access Tokens

讓我們來討論一下access tokens。他們到底是什麼?是一串隨機生成的數字?是uuid?還是別的?
這是一個很好的問題。
這裡是一個比較短的答案:access token在技術上你任何你想要的字串:

· 一個隨機數

· 一個隨機字串

· 一個uuid

· 更多

更詳細的解釋:

· 為客戶端而生成的。

· 驗證token的所有者是你(使用強的簽名)

· 存在過期時間。
有了以上的解釋,你可能會希望去遵守一定的規範。為了不自己處理這些,你可以直接使用JWT(Json Web Token)。這是一個比較新的規範,允許你生成access token。這個規範(RFC7519)滿足一下幾點:

· 可以為客戶端生成

· 可以被建立者驗證

· 在某一具體時間後自動過期

· 可以容納可變的JSON資訊

· 無需查詢API服務,允許使用者本地驗證API憑證,從而減少對API呼叫的次數。

JWTs看起來像隨機生成的字串,在使用的時候你可以像字串那樣儲存他們。這使得取代傳統的access token而使用JWTs非常方便,畢竟它們基本上都是相同的,而JWT有更多的優勢。

JWTs總是以加密的方式被驗證。他們工作的方式如下:

· 在API伺服器的某處儲存一個安全隨機字串。一般是一個比較長的隨機字串(40個字元左右差不多)

· 當你建立一個新的JWT時,你需要將這個隨機串傳遞個JWT類庫來簽署token,同時帶有一些你想儲存的資料,例如使用者ID,email等等。

· token將會被生成,看起來像header.claims.signature——header、claims和signature都是base64加密的字串。

· 講生成的token給使用者,一般是API的使用者,例如移動app。

現在從移動客戶端中,你可以看到儲存在JWT中的任何東西。so如果我有一個JWT,我可以輕鬆地檢視到裡面包含的JSON資料,通常如下所示:

{

"user_id": "e3457285-b604-4990-b902-960bcadb0693",

"scope": "can-read can-write"

}

當然,這是一個100%虛構的例子,但是你可以從中知道,如果你得到這個JWT的副本,你也可以看到儲存在裡面的JSON資訊。

JWT標準支援自動的過期標記,因此你也能夠驗證這個JWT是有效的。無論你使用什麼開發語言,只要在使用JWT庫,你就能驗證JWT的有效性直到過期!

這意味著,如果你使用JWT訪問API服務,則只需驗證JWT,就可以知道你的API呼叫是否可以工作,不需要API呼叫。

現在,一旦你有了一個有效的JWT,你也可以在伺服器端用它做很酷的事情。

假設您已經向移動app釋出了一個包含以下資料的JWT:

{

"user_id": "e3457285-b604-4990-b902-960bcadb0693",

"scope": "can-read can-write"

}

假設移動app上有惡意程式碼能夠修改你的JWT,比如說:

{

"user_id": "e3457285-b604-4990-b902-960bcadb0693",

"scope": "can-read can-write can-delete"

}

如果這個修改過的token被髮送到我們的API伺服器會發生什麼?它會起作用嗎?我們的伺服器會接受這個修改的JWT嗎?

注意!!
當你的API服務收到JWT並進行驗證時,它會做以下幾件事情:

· 通過使用只有伺服器才知道的隨機生成的字串來檢查token,確保它沒有被篡改。如果JWT完全被修改,這個檢查就會失敗,你會知道有人正在試圖做一些令人討厭的事情。

· 同時伺服器會檢查JWT的過期時間,確保它的合法性。so如果客戶端用一個已經過期的token來進行請求,你可以立刻拒絕。

這是很好的功能,因為它使處理驗證/到期/安全更簡單。

在使用JWTs時,你唯一需要記住的就是:不要在JWT中儲存敏感資訊。

謹記以上提到的規則,那麼在使用JWTs時就不會出錯了。

通常你會存一下兩條資訊在JWTs中:

· 使用者帳戶的某種唯一ID。這樣,當您收到此JWT進行身份驗證時,您可以從使用者資料庫中查詢此使用者。

· 使用者許可權。當然如果構建的是所有使用者都能訪問的簡單的API,那麼這個可能是不必要的。但是通過這個,使用者就不需要通過看API文件來了解自己可以做什麼,不可以做什麼,只需要根據看自己的JWT就可以。

以上就是有關於JWT的全部。


相關文章