Saml2 Sustainsys在从iDP回调到Saml2/Acs路由时返回404。

huangapple go评论98阅读模式
英文:

Saml2 Sustainsys return 404 when call back from iDP on route Saml2/Acs

问题

我有以下属性:

IDP: Azure

服务提供者: .Net core 6

客户端: Vue 3

以及以下代码:

  1. var samlConfiguration = GetConfiguration<SamlConfiguration>(configuration);
  2. serviceCollection.AddAuthentication(options =>
  3. {
  4. options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
  5. options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
  6. options.DefaultChallengeScheme = Saml2Defaults.Scheme;
  7. })
  8. .AddCookie()
  9. .AddSaml2(Saml2Defaults.Scheme, options =>
  10. {
  11. options.SPOptions.EntityId = new EntityId(samlConfiguration.ServiceProviderEntityId);
  12. options.SPOptions.ReturnUrl = new Uri(samlConfiguration.AssertionConsumerServiceUrl);
  13. options.SPOptions.PublicOrigin = new Uri(samlConfiguration.PublishOrigin);
  14. var idp = new IdentityProvider(new EntityId(samlConfiguration.IdentityProviderEntityId),
  15. options.SPOptions)
  16. {
  17. LoadMetadata = true,
  18. AllowUnsolicitedAuthnResponse = true,
  19. MetadataLocation = samlConfiguration.MetadataLocation
  20. };
  21. options.IdentityProviders.Add(idp);
  22. });
  23. }
  24. [Route("[controller]")]
  25. [ApiController]
  26. public class Saml2Controller : ControllerBase
  27. {
  28. private readonly SamlConfiguration _samlConfiguration;
  29. private readonly ILogger<Saml2Controller> _logger;
  30. public Saml2Controller(IOptions<SamlConfiguration> options, ILogger<Saml2Controller> logger)
  31. {
  32. _logger = logger;
  33. _samlConfiguration = options.Value;
  34. }
  35. [HttpGet]
  36. public IActionResult Initiate()
  37. {
  38. var authenticationProperties = new AuthenticationProperties
  39. {
  40. RedirectUri = _samlConfiguration.RedirectUri,
  41. };
  42. return Challenge(authenticationProperties, Saml2Defaults.Scheme);
  43. }
  44. [HttpPost("Acs")]
  45. public async Task AssertionConsumerService()
  46. {
  47. try
  48. {
  49. _logger.LogInformation("-------begin AssertionConsumerService-------");
  50. var result = await HttpContext.AuthenticateAsync(Saml2Defaults.Scheme);
  51. if (!result.Succeeded)
  52. {
  53. throw new Exception("SAML authentication failed.");
  54. }
  55. _logger.LogInformation("-------set claims-------");
  56. var claims = new List<Claim>();
  57. claims.AddRange(result.Principal.Claims);
  58. _logger.LogInformation("-------create ClaimsIdentity-------");
  59. var identity = new ClaimsIdentity(claims, "saml");
  60. var principal = new ClaimsPrincipal(identity);
  61. _logger.LogInformation("-------begin SignIn-------");
  62. await HttpContext.SignInAsync(principal);
  63. _logger.LogInformation("-------end SignIn-------");
  64. }
  65. catch (Exception exception)
  66. {
  67. _logger.LogError("in {@className}\n--Exception: {@exception}\n--StackTrace: {@stackTrace}",
  68. nameof(Saml2Controller), exception.Message, exception.StackTrace);
  69. }
  70. }
  71. [HttpGet("logout")]
  72. public IActionResult Logout()
  73. {
  74. HttpContext.SignOutAsync(Saml2Defaults.Scheme).Wait();
  75. return Redirect("/");
  76. }
  77. }

SAML配置如下:

  1. "SamlConfiguration": {
  2. "ServiceProviderEntityId": "https://sp.example.com/Saml2",
  3. "IdentityProviderEntityId": "https://sts.windows.net/{tenantId}/",
  4. "SingleSignOnServiceUrl": "https://login.microsoftonline.com/{tenantId}/Saml2",
  5. "AssertionConsumerServiceUrl": "https://sp.example.com/Saml2/Acs",
  6. "MetadataLocation": "https://login.microsoftonline.com/{tenantId}/federationmetadata/2007-06/federationmetadata.xml?appid={appId}",
  7. "PublishOrigin": "https://sp.example.com",
  8. "RedirectUri": "https://vue3.example.com"
  9. }

当客户端到达401时,将重定向到 "https://sp.example.com/Saml2",然后服务提供者重定向到iDP,登录后返回到 "https://sp.example.com/Saml2/Acs",最后我们需要将SAML响应传递给客户端,客户端处理该响应。

我的问题是路由 "Saml2/Acs" 保留给了Sustainsys.saml2库,因为我们在通过Postman或手动调用该路由时("Saml2/Acs"),会收到404错误。如何解决这个问题呢?

英文:

I have the following property:

IDP: Azure

Service Provider: .Net core 6

Client: Vue 3

and following code:

  1. var samlConfiguration = GetConfiguration&lt;SamlConfiguration&gt;(configuration);
  2. serviceCollection.AddAuthentication(options =&gt;
  3. {
  4. options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
  5. options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
  6. options.DefaultChallengeScheme = Saml2Defaults.Scheme;
  7. })
  8. .AddCookie()
  9. .AddSaml2(Saml2Defaults.Scheme, options =&gt;
  10. {
  11. options.SPOptions.EntityId = new EntityId(samlConfiguration.ServiceProviderEntityId);
  12. options.SPOptions.ReturnUrl = new Uri(samlConfiguration.AssertionConsumerServiceUrl);
  13. options.SPOptions.PublicOrigin = new Uri(samlConfiguration.PublishOrigin);
  14. var idp = new IdentityProvider(new EntityId(samlConfiguration.IdentityProviderEntityId),
  15. options.SPOptions)
  16. {
  17. LoadMetadata = true,
  18. AllowUnsolicitedAuthnResponse = true,
  19. MetadataLocation = samlConfiguration.MetadataLocation
  20. };
  21. options.IdentityProviders.Add(idp);
  22. });
  23. [Route(&quot;[controller]&quot;)]
  24. [ApiController]
  25. public class Saml2Controller : ControllerBase
  26. {
  27. private readonly SamlConfiguration _samlConfiguration;
  28. private readonly ILogger&lt;Saml2Controller&gt; _logger;
  29. public Saml2Controller(IOptions&lt;SamlConfiguration&gt; options, ILogger&lt;Saml2Controller&gt; logger)
  30. {
  31. _logger = logger;
  32. _samlConfiguration = options.Value;
  33. }
  34. [HttpGet]
  35. public IActionResult Initiate()
  36. {
  37. var authenticationProperties = new AuthenticationProperties
  38. {
  39. RedirectUri = _samlConfiguration.RedirectUri,
  40. };
  41. return Challenge(authenticationProperties, Saml2Defaults.Scheme);
  42. }
  43. [HttpPost(&quot;Acs&quot;)]
  44. public async Task AssertionConsumerService()
  45. {
  46. try
  47. {
  48. _logger.LogInformation(&quot;-------begin AssertionConsumerService-------&quot;);
  49. var result = await HttpContext.AuthenticateAsync(Saml2Defaults.Scheme);
  50. if (!result.Succeeded)
  51. {
  52. throw new Exception(&quot;SAML authentication failed.&quot;);
  53. }
  54. _logger.LogInformation(&quot;-------set claims-------&quot;);
  55. var claims = new List&lt;Claim&gt;();
  56. claims.AddRange(result.Principal.Claims);
  57. _logger.LogInformation(&quot;-------create ClaimsIdentity-------&quot;);
  58. var identity = new ClaimsIdentity(claims, &quot;saml&quot;);
  59. var principal = new ClaimsPrincipal(identity);
  60. _logger.LogInformation(&quot;-------begin SignIn-------&quot;);
  61. await HttpContext.SignInAsync(principal);
  62. _logger.LogInformation(&quot;-------end SignIn-------&quot;);
  63. }
  64. catch (Exception exception)
  65. {
  66. _logger.LogError(&quot;in {@className}\n--Exception: {@exception}\n--StackTrace: {@stackTrace}&quot;,
  67. nameof(Saml2Controller), exception.Message, exception.StackTrace);
  68. }
  69. }
  70. [HttpGet(&quot;logout&quot;)]
  71. public IActionResult Logout()
  72. {
  73. HttpContext.SignOutAsync(Saml2Defaults.Scheme).Wait();
  74. return Redirect(&quot;/&quot;);
  75. }
  76. }

The Saml Configuration is as follows:

  1. &quot;SamlConfiguration&quot;: {
  2. &quot;ServiceProviderEntityId&quot;: &quot;https://sp.example.com/Saml2&quot;,
  3. &quot;IdentityProviderEntityId&quot;: &quot;https://sts.windows.net/{tenantId}/&quot;,
  4. &quot;SingleSignOnServiceUrl&quot;: &quot;https://login.microsoftonline.com/{tenantId}/Saml2&quot;,
  5. &quot;AssertionConsumerServiceUrl&quot;: &quot;https://sp.example.com/Saml2/Acs&quot;,
  6. &quot;MetadataLocation&quot;: &quot;https://login.microsoftonline.com/{tenantId}/federationmetadata/2007-06/federationmetadata.xml?appid={appId}&quot;,
  7. &quot;PublishOrigin&quot;: &quot;https://sp.example.com&quot;,
  8. &quot;RedirectUri&quot;: &quot;https://vue3.example.com&quot;
  9. }

When client reach to 401 then redirect to "https://sp.example.com/Saml2" and then Service Provider redirect to iDP and after login returns to "https://sp.example.com/Saml2/Acs" and finally we need to pass the Saml Response to Client and Client prosses that response.

My Problem is route "Saml2/Acs" is reserved for Sustainsys.saml2 library because we get the 404 Error when we call that route ("Saml2/Acs") via Postman or manually.

What can be do to solve this issue?

答案1

得分: 0

你的设计有误。服务器端应用程序处理Saml响应并将生成的身份信息存储在Cookie中(通过调用配置的身份验证方案上的SignInAsync)。对于JavaScript应用程序的建议是使用后端前端模式,在该模式下会话在服务器端处理,详见https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps。

英文:

Your design is wrong. The server side application processes the Saml response and stores the resulting identity in a cookie (by calling SignInAsync on the configured authentication scheme). The recommendation for javascript applications is to use a backend for frontend pattern where the session is handled on the server side, see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps

huangapple
  • 本文由 发表于 2023年2月13日 22:58:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75437565.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定