IdP代理 - SLO SP已启动

时间:2018-05-23 13:51:29

标签: asp.net-core saml-2.0 component-space

我正在尝试构建基于组件空间SAML解决方案的IdP-Proxy。

直到现在我能够以下列方式处理单点登录:

  1. 添加SingleSignOnService方法,该方法从AUTHN收到SP请求,并向合作伙伴SSO发起IdPSP-initiated SSO
  2. 添加一个AssertionConsumerService,其中收到SSO个结果,并标记IsInResponseTo个标记。基于此标志,我确定我是否在SP-initiated SSOIdP-initiated SSO流程中并相应地确定了流程。
  3. 我正尝试使用以下示例流程以相同方式处理单一注销:Single SAMLv2 Identity Provider Proxy Logout

    理论上,对于SP发起的注销,我需要实现以下目标: 1.收到一个退出请求 2.检查它是否不是响应 3.确定IdP 4.向步骤3中确定的IdP发送Slo请求 5.回应SP发起的SLO,表明注销成功。

    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 个答案:

答案 0 :(得分:0)

根据此处列出的ComponentSpace响应:https://www.componentspace.com/Forums/8806/?Update=1#bm8813问题与不等待IdP的响应有关。

根据当前的实施,InitiateSloAsync只会向IdP发送SLO请求,但不会等待响应。

// 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发送退出响应。
  6. 重要提示:在充当身份提供者与服务提供者时,拥有不同的单一注销服务端点可能是有意义的。

    当你扮演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();
    }
    

    P.S:如果最终创建两个不同的端点来处理注销,请不要忘记更新 SingleLogoutServiceUrl 属性。