17

クレーム認証を使用して ASP.NET WebApi 2 を使用して Web API を構築していますが、ユーザーは非常に多くのクレームを持つことができます。多数のクレームがあると、ベアラー トークンが急速に大きくなるため、はるかに短いベアラー トークンを返す方法を見つけようとしています。

IAuthenticationTokenProviderこれまでのところ、OAuth オプションOAuthAuthorizationServerOptions.AccessTokenProviderプロパティに を提供できることを発見しました。

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 スタック内でこれを行う必要がある、より良い/より簡単な場所はありますか?

注意すべきもう 1 つのことは、リフレッシュ トークンをサポートするつもりであるということです。実際、上記の例は、リフレッシュ トークンにこの種のメカニズムを使用する例から引き出されたものです ReceiveAsync。通常、 から提供されたリフレッシュ トークンは常に削除されますが、そのConcurrentDictionary理由がよくわかりません。

4

1 に答える 1

7

最終的には認証チケットをデータベースまたは Redis サーバーに保存することになるため、これを行うことはお勧めしません。ベアラー トークンを含む各リクエストで、この永続的なストアを確認して問題を解決する必要があるという欠点があります。ガイドしてチケットを再度取得し、作成します。

デフォルトのベアラー アクセス トークン形式の代わりにJSON Web トークンJWTを使用することをお勧めします。これを行うには、以下のコードのようCustomOAuthProviderにプロパティProviderでカスタム アクセス トークン形式を実装する必要があります。OAuthAuthorizationServerOptions

 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 のサンプルの下で、2 番目の JWT は最初の JWT よりも 50 文字だけ大きくなっています。jwt.io First JWTを使用して、それぞれのエンコードされたコンテンツを確認することをお勧めします。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InRhaXNlZXIiLCJzdWIiOiJ0YWlzZWVyIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQxODY0NzMyNywibmJmIjoxNDE4NjQ1NTI3fQ.vH9XPtjtAv2-6SwlyX4fKNJfm5ZTVHd_9a3bRgkA_LI

2 番目の JWT (その他のクレーム):

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InRhaXNlZXIiLCJzdWIiOiJ0YWlzZWVyIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciIsIlN1cGVydmlzb3IxIiwiU3VwZXJ2aXNvcjIiLCJTdXBlcnZpc29yMyJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQxODY0NzQ1NiwibmJmIjoxNDE4NjQ1NjU2fQ.TFEGDtz1RN8VmCQu7JH4Iug0B8UlWDLVrIlvc-7IK3E

JWT 形式は、OAuth 2.0 ベアラー トークンを発行する標準的な方法になりつつあり、リフレッシュ トークンの付与でも機能します。ただし、JWT は署名付きトークンのみであり、既定のアクセス トークン形式の場合のように暗号化されていないため、機密データを格納しないでください。

ASP.NET Web API で JWT トークンを使用する方法と、GIthub のライブ デモ API およびソース コードに関する詳細なブログ投稿を bitoftech.net に書きました。

幸運を!

于 2014-12-15T12:33:03.277 に答える