diff --git a/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs b/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs
index 7dac334487..5ecf5cebc1 100644
--- a/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs
+++ b/bitwarden_license/src/Portal/Models/SsoConfigDataViewModel.cs
@@ -31,6 +31,7 @@ namespace Bit.Portal.Models
RedirectBehavior = configurationData.RedirectBehavior;
GetClaimsFromUserInfoEndpoint = configurationData.GetClaimsFromUserInfoEndpoint;
SpEntityId = configurationData.BuildSaml2ModulePath(globalSettings.BaseServiceUri.Sso);
+ SpMetadataUrl = configurationData.BuildSaml2MetadataUrl(globalSettings.BaseServiceUri.Sso, organizationId.ToString());
SpAcsUrl = configurationData.BuildSaml2AcsUrl(globalSettings.BaseServiceUri.Sso, organizationId.ToString());
IdpEntityId = configurationData.IdpEntityId;
IdpBindingType = configurationData.IdpBindingType;
@@ -75,6 +76,8 @@ namespace Bit.Portal.Models
// SAML2 SP
[Display(Name = "SpEntityId")]
public string SpEntityId { get; set; }
+ [Display(Name = "SpMetadataUrl")]
+ public string SpMetadataUrl { get; set; }
[Display(Name = "SpAcsUrl")]
public string SpAcsUrl { get; set; }
[Display(Name = "NameIdFormat")]
diff --git a/bitwarden_license/src/Portal/Views/Sso/Index.cshtml b/bitwarden_license/src/Portal/Views/Sso/Index.cshtml
index 58743d9e93..0f2c0eaa1b 100644
--- a/bitwarden_license/src/Portal/Views/Sso/Index.cshtml
+++ b/bitwarden_license/src/Portal/Views/Sso/Index.cshtml
@@ -156,6 +156,30 @@
+
diff --git a/bitwarden_license/src/Sso/Controllers/MetadataController.cs b/bitwarden_license/src/Sso/Controllers/MetadataController.cs
new file mode 100644
index 0000000000..a114f8e827
--- /dev/null
+++ b/bitwarden_license/src/Sso/Controllers/MetadataController.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Threading.Tasks;
+using Bit.Core.Enums;
+using Bit.Sso.Utilities;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Mvc;
+using Sustainsys.Saml2.AspNetCore2;
+using Sustainsys.Saml2.WebSso;
+
+namespace Bit.Sso.Controllers
+{
+ public class MetadataController : Controller
+ {
+ private readonly IAuthenticationSchemeProvider _schemeProvider;
+
+ public MetadataController(
+ IAuthenticationSchemeProvider schemeProvider)
+ {
+ _schemeProvider = schemeProvider;
+ }
+
+ [HttpGet("saml2/{scheme}")]
+ public async Task ViewAsync(string scheme)
+ {
+ if (string.IsNullOrWhiteSpace(scheme))
+ {
+ return NotFound();
+ }
+
+ var authScheme = await _schemeProvider.GetSchemeAsync(scheme);
+ if (authScheme == null ||
+ !(authScheme is DynamicAuthenticationScheme dynamicAuthScheme) ||
+ dynamicAuthScheme?.SsoType != SsoType.Saml2)
+ {
+ return NotFound();
+ }
+
+ if (!(dynamicAuthScheme.Options is Saml2Options options))
+ {
+ return NotFound();
+ }
+
+ var uri = new Uri(
+ Request.Scheme
+ + "://"
+ + Request.Host
+ + Request.Path
+ + Request.QueryString);
+
+ var pathBase = Request.PathBase.Value;
+ pathBase = string.IsNullOrEmpty(pathBase) ? "/" : pathBase;
+
+ var requestdata = new HttpRequestData(
+ Request.Method,
+ uri,
+ pathBase,
+ null,
+ Request.Cookies,
+ (data) => data);
+
+ var metadataResult = CommandFactory
+ .GetCommand(CommandFactory.MetadataCommand)
+ .Run(requestdata, options);
+ //Response.Headers.Add("Content-Disposition", $"filename= bitwarden-saml2-meta-{scheme}.xml");
+ return new ContentResult
+ {
+ Content = metadataResult.Content,
+ ContentType = "text/xml",
+ };
+ }
+ }
+}
diff --git a/src/Core/Models/Data/SsoConfigurationData.cs b/src/Core/Models/Data/SsoConfigurationData.cs
index 11e7767f55..e3d6675d5d 100644
--- a/src/Core/Models/Data/SsoConfigurationData.cs
+++ b/src/Core/Models/Data/SsoConfigurationData.cs
@@ -62,6 +62,11 @@ namespace Bit.Core.Models.Data
return string.Concat(BuildSaml2ModulePath(ssoUri, scheme), "/Acs");
}
+ public string BuildSaml2MetadataUrl(string ssoUri = null, string scheme = null)
+ {
+ return BuildSaml2ModulePath(ssoUri, scheme);
+ }
+
private string BuildSsoUrl(string relativePath, string ssoUri)
{
if (string.IsNullOrWhiteSpace(ssoUri) ||
diff --git a/src/Core/Resources/SharedResources.en.resx b/src/Core/Resources/SharedResources.en.resx
index a3fd168568..561266824a 100644
--- a/src/Core/Resources/SharedResources.en.resx
+++ b/src/Core/Resources/SharedResources.en.resx
@@ -265,6 +265,9 @@
SP Entity ID
+
+ SAML 2.0 Metadata URL
+
Assertion Consumer Service (ACS) URL
@@ -475,6 +478,12 @@
Copy the SP Entity Id to your clipboard
+
+ Copy the SAML 2.0 Metadata URL to your clipboard
+
+
+ View the SAML 2.0 Metadata (opens in a new window)
+
Copy the Assertion Consumer Service (ACS) URL to your clipboard