2015-04-16 163 views
23

我有一個關於如何構建使用訪問令牌和API密鑰的REST API的問題。構建API密鑰和訪問令牌

我有一個需要驗證的API。我想啓用兩個用例:

  1. 使用的OAuth2(密碼補助金)的用戶登錄到界面,並被授予臨時訪問令牌。該令牌用於認證用戶。因此,使用API​​的UI可以獲取數據並顯示它。

  2. 我也希望用戶有一個API密鑰來執行相同的調用,但在其應用程序。顯然,與訪問令牌相反,我希望API密鑰長期存在。此外,與綁定到給定用戶的訪問令牌相反(如果我們引入團隊機制,每個用戶將擁有不同的訪問令牌,雖然他們訪問相同的資源),但API密鑰應該對項目是唯一的。

雖然相似,但我不確定我應該如何構造它。我認爲,在內部,API密鑰和訪問令牌應該存儲在同一個表中,但API密鑰沒有到期時間。我對嗎?

我不確定的一件事還是客戶端的概念。看來在規範中,客戶端更像是一個外部應用程序。但是我可以在這裏實際使用這個概念嗎?例如,每個「項目」實際上是一個不同的客戶端(雖然這裏的客戶端是同一個應用程序,而不是由第三方開發者創建的應用程序)。

因此,如果用戶A在系統上創建一個帳戶,則客戶端A將自動創建一個訪問令牌,並與一個長期訪問令牌(又名API密鑰)綁定到客戶端A.例如,這可以用來直接在他的代碼上執行API調用。

然後,如果用戶A登錄到儀表板,則會創建一個臨時訪問令牌,但此時沒有應用程序,但與用戶綁定,壽命短。

這聽起來理智?有沒有人已經實現了這樣的事情?

謝謝!

+1

API密鑰和訪問令牌是不同的概念,它們分別進行建模,並將它們分開存儲。 –

+0

是的,但你如何處理我想以同質方式訪問API的事實?我不想有不同的方式來使用API​​。無論是我的Web應用程序使用臨時令牌還是使用API​​密鑰直接從其Web服務器使用API​​的客戶端使用它。 –

回答

14

我想你不應該把「API密鑰」作爲訪問令牌的替代品。

您將不得不使用訪問令牌來承擔請求之間的身份驗證,因此您實際上使用「API密鑰」建模的內容不是替代通常的承載令牌,而是提供了不同的客戶端其他授權類型來請求令牌。

我個人實施流程如下:

  1. 用戶與普通客戶端密碼撥款類型,爲每個用戶(即您的「網絡應用」的客戶端,這是公開的,即認證它沒有client_secret)。
  2. 用戶可以創建自己的客戶端。根據OAuth2規範,這些規範不公開,因此它們將包含client_idclient_secret。這些就是你所說的「API密鑰」。
  3. 用戶隨後可以通過客戶端以任何您希望支持的授權類型(例如直接客戶端憑證,授權代碼,隱式,第三方等)請求訪問令牌。您將不得不對有關如何處理客戶端證書的正確安全做法強調一點。

很顯然,你將必須實現以這樣的方式,客戶可以屬於特定的用戶您的OAuth2服務器,並有不同的接受補助的類型(例如,你可能不希望允許與用戶客戶端的密碼贈款的使用,而您可能想要禁止任何授權類型,而不是您的Web應用程序客戶端的授權類型)。

然後,您將能夠在每個客戶端或每個授權類型的基礎上定義令牌TTL(或缺乏)(例如,通過密碼授權請求的訪問令牌,只能由Web應用程序客戶端使用,將具有短TTL,而授權碼授予將提供長壽命令牌)。
但我建議不要完全缺乏TTL,而應使用refresh_token授予類型來更新過期的訪問令牌。此外,您可能必須定義某種類型的授權系統(ACL,RBAC,無論),以定義哪個客戶端可以執行什麼操作。這意味着每個訪問令牌都應該包含對創建客戶端的引用。

所以,概括起來講,這裏的關係:

用戶客戶
客戶端有一個用戶
客戶端有很多令牌
令牌有一個客戶端
令牌有一個用戶

YMMV雙向。

你應該能夠實現我與任何特定平臺的最常見的OAuth2服務器實施方案所描述的一切。

TL; DR:「API密鑰」實際上是OAuth2 客戶端

+0

謝謝斯特凡諾;)。聽起來很不錯,很合理,雖然我不太喜歡用戶需要同時通過client_secret和client_id(這使事情變得更加複雜)的事實。我試圖通過分析請求來理解Stripe API的工作原理,看起來他們使用基本驗證和生成的API密鑰(他們應該生成)以及使用訪問令牌(他們的Web應用)的載體。 –

+0

那麼,您只需使用一次客戶端憑證即可獲取訪問令牌,而使用基本身份驗證時,則可以使用每個請求發送實際憑據。 這更爲複雜,確實如此,但如果做得對,它也更安全(因爲它與整個OAuth2 vs Basic比較是一樣的)。 –

1

我寫了一篇關於如何使用RESTful應用程序的訪問令牌的文章:https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/。也許這可以提供一些提示。

要回答你的問題,我認爲我們需要有一些同質的東西。我的意思是你所有的認證機制應該基於訪問令牌。您的API密鑰將允許您獲取實際用於身份驗證的訪問令牌。

據我瞭解,你有兩種應用程序的用戶:使用Web UI

  • 最終用戶(通過OAuth2和密碼登陸)
  • 應用程序(使用API​​密鑰登錄)

所以我會實現這兩種用戶,並使他們獲得訪問令牌的能力。訪問令牌將用於訪問RESTful服務。

另外,我認爲這個答案可以給你一些其他的提示:Securing my REST API with OAuth while still allowing authentication via third party OAuth providers (using DotNetOpenAuth)

希望它回答你的問題。 Thierry

2

謝謝您的回答。

我實際上對OAuth2本身非常有經驗,我的問題更多地針對API密鑰。我喜歡交換訪問令牌的API密鑰的想法,但我認爲這是行不通的。 API密鑰是固定的,不會更改,而訪問令牌可能會過期。

問題是:應用程序如何知道這是一個訪問令牌還是API密鑰。我的意思是,好的,比方說,在我的數據庫中,每個用戶的數據庫中都有一個「api_key」列。

與訪問令牌相反,api_key不會過期(儘管用戶最終可以旋轉它)。正如我所說的,我想要的是同質化的認證處理。

案例1:我自己的web應用程序做API調用

的工作流程如下,使用的OAuth2:

  1. 用戶輸入自己的電子郵件/密碼。
  2. 授權服務器返回臨時訪問令牌(例如:「abc」)。
  3. 在Web應用程序中,所有API調用都是使用此令牌完成的。例如:「/ payments/1」,授權標題爲「Bearer abc」。

好又簡單。

案例2:用戶有一個API密鑰,也不會過期,可以私下在自己的應用程序

顯然使用授權機制必須保持不變。所以:

  1. 用戶進入他的賬戶,並且讀取他的API密鑰是「def」。
  2. 在他們的服務器代碼中,他們可以使用相同的身份驗證機制執行相同的調用。因此,他可以通過Authorization:「Bearer def」調用「/ payments/1」。

它必須工作。正如你所看到的,兩個例子都沒有改變。他們訪問相同的資源,相同的授權機制......但在一種情況下,我們有一個訪問令牌,在其他情況下,我們有一個API密鑰。而且我不知道我應該如何從數據庫的角度和授權代碼中實現這一點。

我有一個潛在的想法是使用不同的認證機制。對於OAuth,它將是「授權:承載訪問令牌」,而對於API,它將是基本認證:「授權:基本apiKey」。

聽起來不錯?

相關問題