Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Merge pull request #691 from robthejedi/master
Browse files Browse the repository at this point in the history
Add Federation Metadata Endpoint for HRD
  • Loading branch information
leastprivilege committed Jun 23, 2014
2 parents 90b0508 + 79d2469 commit f827325
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public static class Roles
public static class CacheKeys
{
public const string WSFedMetadata = "Cache_WSFedMetadata";
public const string WSFedRPMetadata = "Cache_WSFedRPMetadata";
}
}
}
8 changes: 8 additions & 0 deletions src/Libraries/Thinktecture.IdentityServer.Core/Endpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class Endpoints
public Uri WSFederation { get; set; }
public Uri WSFederationHRD { get; set; }
public Uri WSFederationMetadata { get; set; }
public Uri WSFederationRPMetadata { get; set; }
public Uri WSTrustMex { get; set; }
public Uri PrivacyNotice { get; set; }

Expand Down Expand Up @@ -43,6 +44,7 @@ public static class Paths
public const string WSFedHRDSelect = "issue/hrd/select";
public const string WSFedHRDSignoutRedirect = "issue/hrd/SignoutRedirect";
public const string WSFedMetadata = "FederationMetadata/2007-06/FederationMetadata.xml";
public const string WSFedRPMetadata = "FederationMetadataRP/2007-06/FederationMetadata.xml";
public const string PrivacyNotice = "privacyNotice.txt";
public const string WSTrustBase = "issue/wstrust";
public const string SimpleHttp = "issue/simple";
Expand Down Expand Up @@ -164,6 +166,12 @@ public static Endpoints Create(string baseUriString, int httpPort, int httpsPort
builder.Scheme = Uri.UriSchemeHttps;
builder.Port = httpsPort;
ep.WSFederationMetadata = builder.Uri;

var wsfedrpmd = new Uri(baseUriString + Paths.WSFedRPMetadata);
builder = new UriBuilder(wsfedrpmd);
builder.Scheme = Uri.UriSchemeHttps;
builder.Port = httpsPort;
ep.WSFederationRPMetadata = builder.Uri;

var adfs = new Uri(baseUriString + Paths.AdfsIntegration);
builder = new UriBuilder(adfs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

using System;
using System.ComponentModel.Composition;
using System.Web;
using System.Web.Mvc;
using Thinktecture.IdentityServer.Helper;
using Thinktecture.IdentityServer.Repositories;
Expand Down Expand Up @@ -60,5 +59,35 @@ public ActionResult Generate()
return new HttpNotFoundResult();
}
}

public ActionResult GenerateRPMetadata()
{
if (ConfigurationRepository.FederationMetadata.Enabled)
{
return Cache.ReturnFromCache<ActionResult>(CacheRepository, Constants.CacheKeys.WSFedRPMetadata, 1, () =>
{
var host = ConfigurationRepository.Global.PublicHostName;
if (String.IsNullOrWhiteSpace(host))
{
host = HttpContext.Request.Headers["Host"];
}
var endpoints = Endpoints.Create(
host,
HttpContext.Request.ApplicationPath,
ConfigurationRepository.Global.HttpPort,
ConfigurationRepository.Global.HttpsPort);
return new ContentResult
{
Content = new WSFederationMetadataGenerator(endpoints).GenerateRelyingPartyMetadata(),
ContentType = "text/xml"
};
});
}
else
{
return new HttpNotFoundResult();
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,47 @@ public WSFederationMetadataGenerator(Endpoints endpoints)
Container.Current.SatisfyImportsOnce(this);
}

//Builds federation metadata for using Id Srv as an IdP using the wsfed endpoint
public string Generate()
{
var tokenServiceDescriptor = GetTokenServiceDescriptor();
var tokenServiceDescriptor = GetTokenServiceDescriptor(_endpoints.WSFederation.AbsoluteUri);
return GenerateMetadata(tokenServiceDescriptor);
}

//Builds federation metadata for using Id Srv as an RP using the HRD endpoint
public string GenerateRelyingPartyMetadata()
{
var tokenServiceDescriptor = GetTokenServiceDescriptor(_endpoints.WSFederationHRD.AbsoluteUri);
var appServiceDescriptor = GetApplicationServiceDescriptor();

return GenerateMetadata(tokenServiceDescriptor, appServiceDescriptor);
}

private string GenerateMetadata(params RoleDescriptor[] roles)
{
var id = new EntityId(ConfigurationRepository.Global.IssuerUri);
var entity = new EntityDescriptor(id);
entity.SigningCredentials = new X509SigningCredentials(ConfigurationRepository.Keys.SigningCertificate);
entity.RoleDescriptors.Add(tokenServiceDescriptor);

foreach (var roleDescriptor in roles)
{
entity.RoleDescriptors.Add(roleDescriptor);
}

var ser = new MetadataSerializer();
var sb = new StringBuilder(512);

ser.WriteMetadata(XmlWriter.Create(new StringWriter(sb), new XmlWriterSettings { OmitXmlDeclaration = true }), entity);
return sb.ToString();
}

private SecurityTokenServiceDescriptor GetTokenServiceDescriptor()
private SecurityTokenServiceDescriptor GetTokenServiceDescriptor(string passiveRequestorEndpoint)
{
var tokenService = new SecurityTokenServiceDescriptor();
tokenService.ServiceDescription = ConfigurationRepository.Global.SiteName;
tokenService.Keys.Add(GetSigningKeyDescriptor());

tokenService.PassiveRequestorEndpoints.Add(new EndpointReference(_endpoints.WSFederation.AbsoluteUri));
tokenService.PassiveRequestorEndpoints.Add(new EndpointReference(passiveRequestorEndpoint));

tokenService.TokenTypesOffered.Add(new Uri(TokenTypes.OasisWssSaml11TokenProfile11));
tokenService.TokenTypesOffered.Add(new Uri(TokenTypes.OasisWssSaml2TokenProfile11));
Expand Down Expand Up @@ -101,6 +120,23 @@ private SecurityTokenServiceDescriptor GetTokenServiceDescriptor()
return tokenService;
}

private ApplicationServiceDescriptor GetApplicationServiceDescriptor()
{
var appDescriptor = new ApplicationServiceDescriptor();

appDescriptor.ServiceDescription = ConfigurationRepository.Global.SiteName;
appDescriptor.Keys.Add(GetSigningKeyDescriptor());

appDescriptor.PassiveRequestorEndpoints.Add(new EndpointReference(_endpoints.WSFederationHRD.AbsoluteUri));
appDescriptor.TokenTypesOffered.Add(new Uri(TokenTypes.OasisWssSaml11TokenProfile11));
appDescriptor.TokenTypesOffered.Add(new Uri(TokenTypes.OasisWssSaml2TokenProfile11));

ClaimsRepository.GetSupportedClaimTypes().ToList().ForEach(claimType => appDescriptor.ClaimTypesOffered.Add(new DisplayClaim(claimType)));
appDescriptor.ProtocolsSupported.Add(new Uri("http://docs.oasis-open.org/wsfed/federation/200706"));

return appDescriptor;
}

private KeyDescriptor GetSigningKeyDescriptor()
{
var certificate = ConfigurationRepository.Keys.SigningCertificate;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

127 changes: 65 additions & 62 deletions src/OnPremise/WebSite/App_LocalResources/Home/Index.cshtml.resx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
<!--
Microsoft ResX Schema
Version 2.0
Expand Down Expand Up @@ -59,71 +59,74 @@
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ApplicationIntegration" xml:space="preserve">
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ApplicationIntegration" xml:space="preserve">
<value>Application integration</value>
</data>
<data name="ViewWsFederationMetadata" xml:space="preserve">
<data name="ViewWsFederationMetadata" xml:space="preserve">
<value>View WS-Federation Metadata</value>
</data>
<data name="WelcomeToSite" xml:space="preserve">
<data name="ViewWSFederationMetadataRP" xml:space="preserve">
<value>View WS-Federation Metadata (RP)</value>
</data>
<data name="WelcomeToSite" xml:space="preserve">
<value>Welcome to {0}</value>
</data>
</root>
6 changes: 6 additions & 0 deletions src/OnPremise/WebSite/App_Start/ProtocolConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public static void RegisterProtocols(HttpConfiguration httpConfiguration, RouteC
// federation metadata
if (configuration.FederationMetadata.Enabled)
{
routes.MapRoute(
"FederationMetadataRP",
Thinktecture.IdentityServer.Endpoints.Paths.WSFedRPMetadata,
new { controller = "FederationMetadata", action = "GenerateRPMetadata" }
);

routes.MapRoute(
"FederationMetadata",
Thinktecture.IdentityServer.Endpoints.Paths.WSFedMetadata,
Expand Down
1 change: 1 addition & 0 deletions src/OnPremise/WebSite/Controller/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public ActionResult AppIntegration()
if (Configuration.FederationMetadata.Enabled)
{
list.Add("WS-Federation metadata", endpoints.WSFederationMetadata.AbsoluteUri);
list.Add("WS-Federation metadata (RP)", endpoints.WSFederationRPMetadata.AbsoluteUri);
}

// ws-federation
Expand Down
4 changes: 4 additions & 0 deletions src/OnPremise/WebSite/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
@Html.ActionLink(Index_cshtml.ViewWsFederationMetadata, "Generate", "FederationMetadata")
</p>

<p>
@Html.ActionLink(Index_cshtml.ViewWSFederationMetadataRP, "GenerateRPMetadata", "FederationMetadata")
</p>

<p>
@Html.ActionLink(Index_cshtml.ApplicationIntegration, "appintegration", "home")
</p>

0 comments on commit f827325

Please sign in to comment.