Приложения ASP.NET, использующие OWIN, допускают использование нескольких источников удостоверений (Facebook, Google и т. д.). Большая часть информации, предоставляемой этими источниками, не имеет отношения к моему приложению, потенциально даже большой, и я не хочу, чтобы она хранилась в моих файлах cookie на протяжении всего сеанса. Мое приложение в основном представляет собой WebAPI, но я подозреваю, что этот вопрос в равной степени относится и к MVC, и к WebForms.
На данный момент все, что мне нужно, это целочисленный идентификатор учетной записи. Где и когда мне следует восстановить личность после внешней аутентификации?
Например, вот один из способов фильтрации утверждений:
public ReplaceExistingClaims(ClaimsIdentity identity) {
{
Claim customClaim = GetCustomClaimFromDbForIdentity(identity);
foreach (Claim claim in ClaimsIdentity.Claims) ClaimsIdentity.RemoveClaim(claim);
ClaimsIdentity.AddClaim(customClaim);
}
Ниже приведены два разных места, где я мог бы вводить эти изменения утверждений:
var facebookAuthenticationOptions = new FacebookAuthenticationOptions
{
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
ReplaceExistingClaims(context.Identity);
return Task.FromResult(0);
}
}
};
Выше я знаю, что могу подключить отдельного провайдера из Startup
, ЕСЛИ он предоставляет событие Authenticated
. У меня есть две концептуальные проблемы с этим. Во-первых, мне нужно написать и подключить свой код отдельно для каждого провайдера, которого я подключаю. Во-вторых, провайдеры не обязаны предоставлять это событие. Оба они заставляют меня чувствовать, что для моего кода должна быть другая предполагаемая точка вставки.
public ActionResult ExternalLoginCallback(string returnUrl)
{
ReplaceExistingClaims((ClaimsIdentity)User.Identity);
new RedirectResult(returnUrl);
}
Выше я знаю, что могу поместить код в ExternalLoginCallback
. Но это происходит слишком поздно по двум причинам. Первый: Пользователю уже выдан тикет, который я считаю недействительным, но [Authorized]
по умолчанию считает действительным, потому что он подписан мной, и теперь они делают запросы на мой сайт с его помощью. Здесь могут быть даже условия гонки. Второе: нет никакой гарантии, что браузер посетит это перенаправление, и я бы предпочел с точки зрения дизайна, если в этом нет необходимости, например. чтобы упростить мой клиентский код WebAPI.
Насколько мне известно, лучшее решение будет соответствовать следующим требованиям:
- один и тот же код применяется ко всем провайдерам
- клиент получает мой пользовательский билет с моего сервера (например, без претензий на изображение)
- клиент никогда не получает другой формат билета с моего сервера
- процесс аутентификации требует минимально возможных двусторонних HTTP-трафиков
- обновление маркера и другие основные функции идентификации по-прежнему доступны
- как только пользователь становится
[Authorize]
d, дальнейшая трансформация учетной записи не требуется. - доступ к базе данных/репозиторию возможен во время создания заявки
Некоторые страницы, которые я изучаю, для собственных заметок:
- Как получить доступ к Microsoft.Owin. Security.xyz Значения AddClaims контекста OnAuthenticated?
- https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Facebook/FacebookAuthenticationHandler.cs
- https://katanaproject.codeplex.com/workitem/82
- https://www.simple-talk.com/dotnet/.net-framework/creating-custom-oauth-middleware-for-mvc-5/