@Refraction

Почему теряется ClaimsPrincipal внутри OWIN middleware?

Здравствуйте.

Столкнулся с проблемой потери ClaimsPrincipal в процессе работы провайдеров OAuth2 middleware. Суть её вот в чем:

Для логирования мне необходимо генерировать Guid в качестве Activity Id. Этот гуид затем используется при вызовах различных датасорсов, чтобы все логи имели единый айди в рамках одного запроса. Так как OAuth middleare зарегистрирован первым, то он и генерирует новое значение activity Id и сохраняет его в клэймах:

public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
    claimsPrincipal.Identities.First.AddClaim(new Claim("TestClaim", Guid.NewGuid().ToString()));

    // много различных асинхронных вызовов датасорсов которые логируются, например:
    await userDataSource.FindAsync(id);
    await tenantDataSource.FindAsync(id);
   //
}


При вызове метода датасорса, из CurrentPrincipal извлекается клэйм и его значение передается в логгер.

И всё вроде бы хорошо, но если до и во время вызова userDataSource клэйе присутствует, то после завершения его вызова и до вызова tenantDataSource клэйма уже нет.
Решив, что owin запускает все middleware с ConfigureAwait(false) что приводит к потере контекста, вынес вызовы датасорсов в отдельный метод, который вызвал c ConfigureAwait(true) в надежде, что контекст не потеряется:

await Grant().ConfigureAwait(true);

Но это не помогло и после возврата из первого асинхронного вызова принципал теряется.
Если же я устанавливаю клэйм в методе Api контроллера, то он доступен на протяжении всего вызова сколько бы ни было внутри вызовов.
Это какая-то особая магия работы с OWIN? Подскажите, пожалуйста, почему это происходит и как предотвратить потерю принципла с установленными мною клэймами?

PS. Еще один интересный для себя нюанс обнаружил:

Если смотреть в Principal в контроллере, то его Identity и Identities[0] ссылаются на один объект, когда как внутри middleware Identity и Identities[0] - два разных экземпляра. Более того, в отличие от контроллера, где Principal - ClaimsPrincipal, внутри middleware он - GenericPrincipal.
Инфы, почему это так, я, к сожалению, не нашел. Буду рад, если кто-нибудь кинет ссылку почитать.

Update

Квыряясь дальше, наткнулся, что в контексте овина Request.User == null. Создав новый принципал и занеся его в User, CurrentPrincipal перестал теряться, и более того, он ссылается на инстанс, занесенный мною в Request.User.

Но я до сих пор не могу найти инфы почему такое происходит и с чего вдруг при возврате контекста из await принципал восстанавливается из Request.User.
Буду рад если кто разъяснит этот момент.
  • Вопрос задан
  • 2490 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы