IdP Proxy - инициировано SLO SP

Я пытаюсь создать IdP-прокси на основе SAML-решения компонентного пространства.

До сих пор я мог обрабатывать единый вход следующим образом:

  1. Добавить SingleSignOnService метод, который получает AUTHN требовать от SP и инициирует SSO к партнеру IdP (SP-initiated SSO).
  2. Добавить AssertionConsumerService который получает SSO результат и чеки IsInResponseTo флаг. На основании этого флага я определил, если я в SP-initiated SSO или в IdP-initiated SSO поток и завершил поток соответственно.

Я пытаюсь обработать одиночный выход таким же образом, используя следующий пример: Выход из одного прокси-сервера провайдера идентификации SAMLv2

Теоретически, для инициированного 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();

Процесс следующий:

  1. Получить запрос на выход из системы SP.
  2. Определить IdP.
  3. Отправить запрос на выход из IdP.
  4. Получите ответ выхода из IdP.
  5. Отправить ответ выхода из системы 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, если в итоге вы создадите две разные конечные точки для обработки выхода из системы.

Другие вопросы по тегам