IdP 代理 - SLO SP 启动
IdP Proxy - SLO SP initiated
我正在尝试构建一个基于 component-space SAML 解决方案的 IdP-Proxy。
到目前为止,我能够通过以下方式处理单点登录:
- 添加一个
SingleSignOnService
方法,该方法从 SP
接收 AUTHN
请求并向合作伙伴 IdP
发起 SSO
(SP-initiated SSO
).
- 添加一个
AssertionConsumerService
接收 SSO
结果并检查 IsInResponseTo
标志。基于这个标志,我确定了我是在 SP-initiated SSO
还是在 IdP-initiated SSO
流程中,并相应地确定了流程。
我正在尝试使用以下示例流程以相同的方式处理单次注销:
理论上,对于 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 步)。
我遗漏了什么吗"protocol-wise"?
附件(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;
}
}
根据此处列出的 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();
过程如下:
- 收到来自 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();
}
P.S:如果您最终创建了两个不同的端点来处理注销,请不要忘记更新您的 SingleLogoutServiceUrl 属性。
我正在尝试构建一个基于 component-space SAML 解决方案的 IdP-Proxy。
到目前为止,我能够通过以下方式处理单点登录:
- 添加一个
SingleSignOnService
方法,该方法从SP
接收AUTHN
请求并向合作伙伴IdP
发起SSO
(SP-initiated SSO
). - 添加一个
AssertionConsumerService
接收SSO
结果并检查IsInResponseTo
标志。基于这个标志,我确定了我是在SP-initiated SSO
还是在IdP-initiated SSO
流程中,并相应地确定了流程。
我正在尝试使用以下示例流程以相同的方式处理单次注销:
理论上,对于 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 步)。
我遗漏了什么吗"protocol-wise"?
附件(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;
}
}
根据此处列出的 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();
过程如下:
- 收到来自 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();
}
P.S:如果您最终创建了两个不同的端点来处理注销,请不要忘记更新您的 SingleLogoutServiceUrl 属性。