Я создаю веб-api, используя ASP.NET WebApi 2, используя проверку подлинности, и мои пользователи могут иметь очень большое количество претензий. С большим количеством требований токен-носитель быстро растет очень быстро, поэтому я пытаюсь найти способ возврата гораздо более короткого токена-носителя.
До сих пор я обнаружил, что могу предоставить 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?
Еще одна вещь, которую следует отметить, это то, что я намерен поддерживать токены обновления, и на самом деле приведенный выше пример был вырван из примеров, которые используют этот механизм для токена Refresh - кроме как с токеном обновления, они кажутся одноразовыми, поэтому метод ReceiveAsync
обычно всегда удаляет токен обновления, указанный в ConcurrentDictionary
, я не совсем уверен, что понимаю, почему?