1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-22 12:15:36 +01:00

Add SAML 2.0 metadata export for dynamic SPs (#1094)

This commit is contained in:
Chad Scharf 2021-01-21 15:54:46 -05:00 committed by GitHub
parent bc1a20101a
commit 85edc03461
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 113 additions and 0 deletions

View File

@ -31,6 +31,7 @@ namespace Bit.Portal.Models
RedirectBehavior = configurationData.RedirectBehavior; RedirectBehavior = configurationData.RedirectBehavior;
GetClaimsFromUserInfoEndpoint = configurationData.GetClaimsFromUserInfoEndpoint; GetClaimsFromUserInfoEndpoint = configurationData.GetClaimsFromUserInfoEndpoint;
SpEntityId = configurationData.BuildSaml2ModulePath(globalSettings.BaseServiceUri.Sso); SpEntityId = configurationData.BuildSaml2ModulePath(globalSettings.BaseServiceUri.Sso);
SpMetadataUrl = configurationData.BuildSaml2MetadataUrl(globalSettings.BaseServiceUri.Sso, organizationId.ToString());
SpAcsUrl = configurationData.BuildSaml2AcsUrl(globalSettings.BaseServiceUri.Sso, organizationId.ToString()); SpAcsUrl = configurationData.BuildSaml2AcsUrl(globalSettings.BaseServiceUri.Sso, organizationId.ToString());
IdpEntityId = configurationData.IdpEntityId; IdpEntityId = configurationData.IdpEntityId;
IdpBindingType = configurationData.IdpBindingType; IdpBindingType = configurationData.IdpBindingType;
@ -75,6 +76,8 @@ namespace Bit.Portal.Models
// SAML2 SP // SAML2 SP
[Display(Name = "SpEntityId")] [Display(Name = "SpEntityId")]
public string SpEntityId { get; set; } public string SpEntityId { get; set; }
[Display(Name = "SpMetadataUrl")]
public string SpMetadataUrl { get; set; }
[Display(Name = "SpAcsUrl")] [Display(Name = "SpAcsUrl")]
public string SpAcsUrl { get; set; } public string SpAcsUrl { get; set; }
[Display(Name = "NameIdFormat")] [Display(Name = "NameIdFormat")]

View File

@ -156,6 +156,30 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-7 form-group">
<label asp-for="Data.SpMetadataUrl">@i18nService.T("SpMetadataUrl")</label>
<div class="input-group">
<input asp-for="Data.SpMetadataUrl" class="form-control" readonly>
<div class="input-group-append">
<a class="btn btn-outline-secondary launch-button"
href="@Model.Data.SpMetadataUrl"
target="_blank"
aria-label="@i18nService.T("LaunchSpMetadataUrl")" title="@i18nService.T("LaunchSpMetadataUrl")"
tabindex="-1">
<i class="fa fa-lg fa-external-link" aria-hidden="true"></i>
</a>
<button type="button" class="btn btn-outline-secondary copy-button"
aria-label="@i18nService.T("CopySpMetadataUrl")" title="@i18nService.T("CopySpMetadataUrl")"
tabindex="-1">
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="col-1">
</div>
</div>
<div class="row"> <div class="row">
<div class="col-7 form-group"> <div class="col-7 form-group">
<label asp-for="Data.SpAcsUrl">@i18nService.T("SpAcsUrl")</label> <label asp-for="Data.SpAcsUrl">@i18nService.T("SpAcsUrl")</label>

View File

@ -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<IActionResult> 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",
};
}
}
}

View File

@ -62,6 +62,11 @@ namespace Bit.Core.Models.Data
return string.Concat(BuildSaml2ModulePath(ssoUri, scheme), "/Acs"); 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) private string BuildSsoUrl(string relativePath, string ssoUri)
{ {
if (string.IsNullOrWhiteSpace(ssoUri) || if (string.IsNullOrWhiteSpace(ssoUri) ||

View File

@ -265,6 +265,9 @@
<data name="SpEntityId" xml:space="preserve"> <data name="SpEntityId" xml:space="preserve">
<value>SP Entity ID</value> <value>SP Entity ID</value>
</data> </data>
<data name="SpMetadataUrl" xml:space="preserve">
<value>SAML 2.0 Metadata URL</value>
</data>
<data name="SpAcsUrl" xml:space="preserve"> <data name="SpAcsUrl" xml:space="preserve">
<value>Assertion Consumer Service (ACS) URL</value> <value>Assertion Consumer Service (ACS) URL</value>
</data> </data>
@ -475,6 +478,12 @@
<data name="CopySpEntityId"> <data name="CopySpEntityId">
<value>Copy the SP Entity Id to your clipboard</value> <value>Copy the SP Entity Id to your clipboard</value>
</data> </data>
<data name="CopySpMetadataUrl">
<value>Copy the SAML 2.0 Metadata URL to your clipboard</value>
</data>
<data name="LaunchSpMetadataUrl">
<value>View the SAML 2.0 Metadata (opens in a new window)</value>
</data>
<data name="CopySpAcsUrl"> <data name="CopySpAcsUrl">
<value>Copy the Assertion Consumer Service (ACS) URL to your clipboard</value> <value>Copy the Assertion Consumer Service (ACS) URL to your clipboard</value>
</data> </data>