IdP Proxy - инициировано SLO SP
Я пытаюсь создать IdP-прокси на основе SAML-решения компонентного пространства.
До сих пор я мог обрабатывать единый вход следующим образом:
- Добавить
SingleSignOnService
метод, который получаетAUTHN
требовать отSP
и инициируетSSO
к партнеруIdP
(SP-initiated SSO
). - Добавить
AssertionConsumerService
который получаетSSO
результат и чекиIsInResponseTo
флаг. На основании этого флага я определил, если я вSP-initiated SSO
или вIdP-initiated SSO
поток и завершил поток соответственно.
Я пытаюсь обработать одиночный выход таким же образом, используя следующий пример:
Теоретически, для инициированного SP выхода из системы мне необходимо добиться следующего: 1. Получить один запрос на выход из системы 2. Проверить, не является ли это ответом 3. Определить IdP 4. Отправить запрос Slo в IdP, определенный на шаге 3 5. Ответьте на SLO, инициированный SP, указывая успешный выход из системы.
public async Task<IActionResult> SingleLogoutService()
{
// Receive the single logout request or response.
// If a request is received then single logout is being initiated by a partner service provider.
// If a response is received then this is in response to single logout having been initiated by the identity provider.
var sloResult = await _samlIdentityProvider.ReceiveSloAsync();
if (sloResult.IsResponse)
{
}
else
{
// Figure out IdP Partner Name
var idpPartnerName = _configuration["IdPPartnerName"];
// Send logout request to idp partner
await _samlServiceProvider.InitiateSloAsync(idpPartnerName, sloResult.LogoutReason, sloResult.RelayState);
// Respond to the SP-initiated SLO request indicating successful logout.
await _samlIdentityProvider.SendSloAsync();
}
return new EmptyResult();
}
Я могу уничтожить сеанс в конце SP, но не могу удалить сеанс IdP (я думаю, что
await _samlServiceProvider.InitiateSloAsync(idpPartnerName, sloResult.LogoutReason, sloResult.RelayState);
должен инициировать удаление сеанса IdP, являясь 3-м шагом в процессе присоединенного прокси).
Что-то, чего мне не хватает, "по протоколу"?
Приложение (InitiateSloAsync
метод):
public async Task InitiateSloAsync(string partnerName, string logoutReason, string relayState)
{
int num;
if ((uint) num <= 5U)
;
try
{
this.logger.LogDebug("Initiating SLO to the partner identity provider" + (string.IsNullOrEmpty(partnerName) ? "." : string.Format(" {0}.", (object) partnerName)), Array.Empty<object>());
await this.LoadSamlStateAsync();
this.LogSessionState();
await this.GetLocalSpConfigurationAsync();
if (this.SamlState.ServiceProviderSessionState.PendingResponseState != null)
this.logger.LogDebug(string.Format("The pending SAML action {0} is being overridden.", (object) this.SamlState.ServiceProviderSessionState.PendingResponseState.Action), Array.Empty<object>());
if (string.IsNullOrEmpty(partnerName) && this.SamlState.ServiceProviderSessionState.SsoSessions.Count == 1)
{
IEnumerator<SsoSessionState> enumerator = this.SamlState.ServiceProviderSessionState.SsoSessions.Values.GetEnumerator();
enumerator.MoveNext();
partnerName = enumerator.Current.PartnerName;
enumerator = (IEnumerator<SsoSessionState>) null;
}
await this.GetPartnerIdpConfigurationAsync(partnerName);
if (this.partnerIdentityProviderConfiguration.DisableOutboundLogout)
throw new SamlProtocolException(string.Format("Logout to the partner identity provider {0} is disabled.", (object) partnerName));
XmlElement xmlElement = await this.CreateLogoutRequestAsync(logoutReason);
XmlElement logoutRequestElement = xmlElement;
xmlElement = (XmlElement) null;
await this.SendLogoutRequestAsync(logoutRequestElement, relayState);
this.SamlState.ServiceProviderSessionState.SsoSessions.Remove(this.partnerIdentityProviderConfiguration.Name);
SamlSubject.OnLogoutRequestSent(partnerName, logoutRequestElement, relayState);
await this.SaveSamlStateAsync();
this.LogSessionState();
this.logger.LogDebug(string.Format("Initiation of SLO to the partner identity provider {0} has completed successfully.", (object) partnerName), Array.Empty<object>());
logoutRequestElement = (XmlElement) null;
}
catch (Exception ex)
{
this.logger.LogError((EventId) 101, ex, string.Format("Initiation of SLO to the partner identity provider {0} has failed.", (object) partnerName), Array.Empty<object>());
throw;
}
}
1 ответ
Согласно ответу ComponentSpace, указанному здесь: https://www.componentspace.com/Forums/8806/?Update=1 проблема связана с не ожиданием ответа от IdP.
Согласно текущей реализации InitiateSloAsync
будет только отправлять запрос SLO в IdP, но не будет ждать ответа.
// Send logout request to idp partner
await _samlServiceProvider.InitiateSloAsync(idpPartnerName, sloResult.LogoutReason, sloResult.RelayState);
// Respond to the SP-initiated SLO request indicating successful logout.
await _samlIdentityProvider.SendSloAsync();
Процесс следующий:
- Получить запрос на выход из системы SP.
- Определить IdP.
- Отправить запрос на выход из IdP.
- Получите ответ выхода из IdP.
- Отправить ответ выхода из системы SP.
Важное замечание. Может иметь смысл иметь разные конечные точки службы единого выхода из системы, когда они выступают в роли поставщика удостоверений и поставщика услуг.
Когда вы действуете как IdP:
public async Task<IActionResult> SingleLogoutService()
{
// Receive the single logout request or response.
// If a request is received then single logout is being initiated by a partner service provider.
// If a response is received then this is in response to single logout having been initiated by the identity provider.
var sloResult = await _samlIdentityProvider.ReceiveSloAsync();
if (sloResult.IsResponse)
{
}
else
{
// Figure out IdP Partner Name
var idpPartnerName = _configuration["IdPPartnerName"];
// Send logout request to idp partner
await _samlServiceProvider.InitiateSloAsync(idpPartnerName, sloResult.LogoutReason, sloResult.RelayState);
}
return new EmptyResult();
}
Когда вы действуете как SP:
public async Task<IActionResult> SingleLogoutService()
{
// Receive the single logout request or response.
// If a request is received then single logout is being initiated by the identity provider.
// If a response is received then this is in response to single logout having been initiated by the service provider.
var sloResult = await _samlServiceProvider.ReceiveSloAsync();
if (sloResult.IsResponse)
{
// Respond to the SP-initiated SLO request indicating successful logout.
await _samlIdentityProvider.SendSloAsync();
}
else
{
}
return new EmptyResult();
}
PS: не забудьте обновить свойства SingleLogoutServiceUrl, если в итоге вы создадите две разные конечные точки для обработки выхода из системы.