I have a WCF service which is hosted in an exe using the ServiceHost class. I call it a "web service" because it's listening via https, so I can ping it from a web browser. (Sorry if not all my terms are precise.)
I would like to enable HSTS for this web service. I found that I can enable it by putting this into the Web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000"/>
</customHeaders>
</httpProtocol>
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
But I don't have a Web.config, because the service is NOT hosted in IIS. I have tried to add this into the system.ServiceModel section but was ineffective. I'm not sure if the system.webServer section could be processed without IIS support or not. I'm also not sure if HSTS is a valid concept at all without IIS (or Apache).
All the articles I read so far, only described the IIS scenario.
https://www.hanselman.com/blog/how-to-enable-http-strict-transport-security-hsts-in-iis7
https://learn.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/hsts
https://www.forwardpmx.com/insights/blog/the-ultimate-guide-to-hsts-protocol/
So my question is: how can I enable the HSTS in this scenario?
Edit: my servicemodel config(edited to eclipse our product name)
<system.serviceModel>
<services>
<service behaviorConfiguration="AServiceBehavior" name="something.RemoteAccess.WebAccess.A.Core.A">
<endpoint address="" behaviorConfiguration="AEndpointBehaviour" binding="basicHttpBinding" bindingConfiguration="secureBasicHttpBinding" name="A" bindingNamespace="uri:something.RemoteAccess.WebAccess.A" contract="something.RemoteAccess.WebAccess.A.IService"/>
<host>
<baseAddresses>
<add baseAddress="https://*:4510/somethingWebAccess/A"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="AEndpointBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="AServiceBehavior">
<serviceMetadata httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I have tried to add this into the
<system.ServiceModel>
section but was ineffective. I'm not sure if the<system.webServer>
section could be processed without IIS support or not. I'm also not sure if HSTS is a valid concept at all without IIS (or Apache).
Correct. The <system.webServer>
element is specific to IIS 7 and later (including IIS Express).
The schema of app.config
and web.config
files is well-defined - it isn't magic: moving elements around won't cause functionality in on library to suddenly work in another, unrelated library.
(Though there is some commonality between <system.web>
(ASP.NET) and <system.webServer>
(IIS), that's just a coincidence - or because of the Managed Pipeline system, I can see why this would cause confusion0.
Your <rewrite>
section will not work at all because that depends on both IIS and having the IIS URL Rewrite module installed (it's an optional component, not installed by default).
I'm also not sure if HSTS is a valid concept at all without IIS (or Apache).
HSTS applies to any HTTP service: it just means that the web-server (or web-application, it doesn't have to be a host/server concern) is sending the Strict-Transport-Security
header.
You can still do this in WCF.
WebOperationContext
:See WCF adding additional HTTP header to HTTP response for transporting SOAP message
var context = WebOperationContext.Current;
if( context is null ) throw new InvalidOperationContext( "WebOperationContext not found. Are you running in the right thread?" );
context.OutgoingResponse.Headers.Add( "Strict-Transport-Security", "max-age=31536000" );
Downside: you'll need to add this code (or a call to a function that implements this code) to all of your WCF actions/endpoints/etc. The advantage here is that you don't need to worry about understanding WCF's "behavior" system.
IClientMessageInspector
:See https://weblogs.asp.net/paolopia/writing-a-wcf-message-inspector
Kinda complicated for me to summarize here, sorry.
It's been literally a full decade since I last wrote any WCF code and I've forgotten how to do custom behaviors. Sorry I can't be of more use :/