簡體   English   中英

通過提供代理令牌處理來自webapi的長持有令牌

[英]Dealing with long bearer tokens from webapi by providing a surrogate token

我正在使用ASP.NET WebApi 2使用聲明身份驗證構建Web api,我的用戶可以擁有大量的聲明。 由於大量聲明,承載令牌迅速增長非常大,因此我試圖找到一種返回更短的承載令牌的方法。

到目前為止,我發現我可以為OAuth選項OAuthAuthorizationServerOptions.AccessTokenProvider屬性提供IAuthenticationTokenProvider

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AccessTokenExpireTimeSpan = TimeSpan.FromHours(12),
    AccessTokenProvider = new GuidProvider() // <-- here
};

這讓我有機會攔截AuthenticationTicket並將其藏起來,用更簡單的東西取而代之 - 在我的例子下面是一個散列的guid。 (注意:目前這個類只包含一個ConcurrentDictionary<string,AuthenticationTicket>和我的會話 - 在一個真實世界的例子中,我打算將會話存儲在一些持久存儲中)

public class GuidProvider : IAuthenticationTokenProvider
{
    private static ConcurrentDictionary<string, AuthenticationTicket> tokens 
        = new ConcurrentDictionary<string, AuthenticationTicket>();

    public void Create(AuthenticationTokenCreateContext context)
    {
        throw new NotImplementedException();
    }

    public async System.Threading.Tasks.Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        var guid = Guid.NewGuid().ToString();

        var ticket = Crypto.Hash(guid);

        tokens.TryAdd(ticket, context.Ticket);

        context.SetToken(ticket);
    }

    public void Receive(AuthenticationTokenReceiveContext context)
    {
        throw new NotImplementedException();
    }

    public async System.Threading.Tasks.Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {
        AuthenticationTicket ticket;

        if (tokens.TryGetValue(context.Token, out ticket))
        {
            if (ticket.Properties.ExpiresUtc.Value < DateTime.UtcNow)
            {
                tokens.TryRemove(context.Token, out ticket);
            }
            context.SetTicket(ticket);
        }
    }
}

所以我的問題:

  • 這是一種適當(且安全!)的方式來提供代理密鑰來代替我的長索賠生成令牌嗎?
  • 是否有更好/更容易的地方我應該在webapi / OAuth堆棧中執行此操作?

另外需要注意的是,我打算支持刷新令牌,實際上上面的示例是從使用這種機制的示例中提取的刷新令牌 - 除了刷新令牌它們似乎是單用的,因此ReceiveAsync方法通常會一直刪除ConcurrentDictionary提供的刷新令牌,我不完全確定我理解為什么?

我建議不要這樣做,因為您最終要將身份驗證票證存儲到數據庫或Redis服務器中,這里的抽獎表示每個請求包含一個不記名令牌,您將檢查此永久存儲以便解決Guid並再次獲得機票以構建它。

我建議您使用JSON Web Token JWT而不是默認的承載訪問令牌格式,為此,您需要在OAuthAuthorizationServerOptions屬性Provider中實現自定義訪問令牌格式CustomOAuthProvider ,如下所示:

 OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            //For Dev enviroment only (on production should be AllowInsecureHttp = false)
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/oauth2/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = new CustomOAuthProvider(),
            AccessTokenFormat = new CustomJwtFormat("http://jwtauthzsrv.azurewebsites.net")
        };

我注意到,對JWT令牌添加更多聲明不會像默認訪問令牌格式那樣大幅增加其大小。

在每個內部具有不同聲明的2個JWT的樣本下面,第二個JWT比第一個僅大50個字符大。 我建議你使用jwt.io來檢查每個的編碼內容First JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InRhaXNlZXIiLCJzdWIiOiJ0YWlzZWVyIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQxODY0NzMyNywibmJmIjoxNDE4NjQ1NTI3fQ.vH9XPtjtAv2-6SwlyX4fKNJfm5ZTVHd_9a3bRgkA_LI

第二次JWT(更多聲明):

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InRhaXNlZXIiLCJzdWIiOiJ0YWlzZWVyIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciIsIlN1cGVydmlzb3IxIiwiU3VwZXJ2aXNvcjIiLCJTdXBlcnZpc29yMyJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQxODY0NzQ1NiwibmJmIjoxNDE4NjQ1NjU2fQ.TFEGDtz1RN8VmCQu7JH4Iug0B8UlWDLVrIlvc-7IK3E

JWT格式正在成為發布OAuth 2.0承載令牌的標准方式,並且它將與刷新令牌授權一起使用。 但請記住,JWT只是簽名的令牌,而不是默認訪問令牌格式的情況,因此不要存儲機密數據。

我在bitoftech.net上寫關於如何在ASP.NET Web API中使用JWT令牌以及在GIthub上使用實時演示API和源代碼的 詳細博客文章 ,請隨時查看它,如果您需要更多幫助,請告訴我。

祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM