У меня проблема с правильным возвратом в клиентское приложение после успешного выхода из системы.Сначала я хотел бы описать мои настройки.
- IdentityServer4 как IDP
- 2x ASP.NET Core MVC-приложение (клиент с точки зрения IS4).В приложениях MVC используются две схемы аутентификации (схема на основе oidc-cookie для аутентификации и схема токенов на предъявителя JWT для вызовов остальных API)
- 2x Angular 7 SPA (который размещается в вышеупомянутом приложении MVC)
Поскольку мой проект предъявляет высокие требования к безопасности, я использую Гибридный поток для авторизации. Итак, процесс входа в систему выглядит следующим образом:
- Пользователь не прошел проверку подлинности и посещает приложение SPA, где он нажимает кнопку входа
- Приложение Angular делает перенаправление наконечная точка MVC, которая находится под атрибутом [Authorize], который инициирует вызов OIDC.
- Пользователь перенаправляется (OidcMiddleware) на IS4, где он может ввести имя пользователя и пароль
- Пользователь находится в процессеперенаправляется (после успешного входа в систему) обратно в логику конечной точки входа MVC (которая была вызвана в п. 2), которая отвечает за перенаправление пользователя обратно в Angular SPA.
- Angular делает вызов http для конечной точки MVC,находится под [Авторизация] и отвечает за возврат сгенерированного токеном JWT IS4 клиенту.
- Поскольку пользователь вошел в клиент MVC (файлы cookie присутствуют), бэкэнд MVC извлекает токен JWT (access_token) изфайл cookie и вернуть его клиенту
- В этот момент поток входа в систему завершен (угловое использование для REST APЯ вызываю токен JWT) - из-за этого я использую на бэкенде две схемы аутентификации.
Так что теперь я столкнулся с некоторыми проблемами с функциональностью выхода из системы.Сначала хотелось бы описать поток для выхода из системы:
- При входе пользователь нажимает кнопку «Выйти» в угловом приложении
Приложение Spa очищает записи localalstorage (гдеТокен JWT сохраняется) и перенаправляет пользователя к действию выхода из системы в приложении MVC.Код ниже:
[AllowAnonymous] публичная асинхронная задача Выход из системы (string returnUrl) {await HttpContext.SignOutAsync ("Cookies");await HttpContext.SignOutAsync ("oidc");}
SignoutAsync на схеме "oidc" запускает поток выхода OIDC (который перенаправляет на конечную точку выхода IS4)
Конечная точка выхода из IS4загрузка контекста выхода из системы (код из быстрого запуска IS4)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutDto dto)
{
// build a model so the logged out page knows what to display
var vm = await BuildLoggedOutViewModelAsync(dto.LogoutId);
if (User?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
await HttpContext.SignOutAsync();
// raise the logout event
await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
}
// check if we need to trigger sign-out at an upstream identity provider
if (vm.TriggerExternalSignout)
{
// build a return URL so the upstream provider will redirect back
// to us after the user has logged out. this allows us to then
// complete our single sign-out processing.
string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
// this triggers a redirect to the external provider for sign-out
return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
}
return View("LoggedOut", vm);
}
Важным является метод BuildLoggedOutViewModelAsync, который загружает контекст выхода из системы:
частная асинхронная задача BuildLoggedOutViewModelAsync (строка logoutId)) {// получить контекстную информацию (имя клиента, URI перенаправления после выхода из системы и iframe для федеративного выхода) var context = await _interaction.GetLogoutContextAsync (logoutId);
var vm = new LoggedOutViewModel
{
AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut,
PostLogoutRedirectUri = context?.PostLogoutRedirectUri,
ClientName = string.IsNullOrEmpty(context?.ClientName) ? context?.ClientId : context?.ClientName,
SignOutIframeUrl = context?.SignOutIFrameUrl,
LogoutId = logoutId
};
if (User?.Identity.IsAuthenticated == true)
{
var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider)
{
var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);
if (providerSupportsSignout)
{
if (vm.LogoutId == null)
{
// if there's no current logout context, we need to create one
// this captures necessary info from the current logged in user
// before we signout and redirect away to the external IdP for signout
vm.LogoutId = await _interaction.CreateLogoutContextAsync();
}
vm.ExternalAuthenticationScheme = idp;
}
}
}
return vm;
}
И вотпроблема.В случае, если срок действия моего cookie-файла mvc истек, в большинстве контекстных свойств установлено значение null, как, например, PostLogoutRedirectUrl.И из-за этого я не могу отобразить ссылку возврата к клиенту в представлении IS4 LoggedOut.cshtml.
В случае, если мой cookie-файл клиента mvc не являетсяистек (действителен) все работает нормально.У меня есть PostLogoutRedirectUrl, который позволяет мне вернуться из IS4 обратно к клиенту, который вызвал выход.
Ребята, у вас есть какие-нибудь идеи, как я могу решить эту проблему?Большое спасибо заранее!