I have set up a WCF service that runs in ASP.NET compatibility mode so that I can take advantage of the SSO authentication that the rest of my site uses. The SSO is based off of Jasig's CAS and I've modified the dotNetCasClient so that it will work with WCF services. The idea is that the dotNetCasClient http module intercepts any requests made to the service and sets up the principal according to the tickets that CAS provides.
To get this work I had to deny access to all anonymous users with:
<system.web>
...
<authorization>
<deny users="?" />
</authorization>
...
</system.web>
Everything up to this point works. Authenticated users can call my service while unauthenticated users are turned away. The problem is that I am unable to access my WSDL through .svc?wsdl. I simply get a 401.2.
Is there a way for me to allow anonymous traffic to my WSDL while still denying anonymous traffic to the rest of my service?
I've tried using variations of the following, but it doesn't like having the ?wsdl in the path.
<location path=path/to/svc?wsdl>
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
I've also played around with allowing anonymous traffic and using the PrincipalPermissionAttribute instead, but this isn't working likely due to the fact that I am using custom principals through the dotNetCasClient rather than windows principals.
Note that if I remove the authorization tags from my web.config I once again can access the WSDL, but that will prevent the SSO authentication from working properly.
Here is my complete web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="casServiceClientConfig" type="DotNetCasClient.Configuration.CasClientConfiguration, DotNetServiceCasClient" />
</configSections>
<system.web>
<compilation debug="true" targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
<authentication mode="Forms">
<forms loginUrl="https://XXXX/cas/login" cookieless="UseCookies" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.web>
<casServiceClientConfig casServerLoginUrl="https://XXXX/cas/login"
casServerUrlPrefix="https://XXXX/cas/"
serverName="https://XXXX"
notAuthorizedUrl="~/NotAuthorized.aspx"
cookiesRequiredUrl="~/CookiesRequired.aspx"
redirectAfterValidation="true"
renew="false"
singleSignOut="true"
ticketValidatorName="Cas20"
serviceTicketManager="CacheServiceTicketManager"
proxyTicketManager="CacheProxyTicketManager"
/>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="DotNetCasClient" />
<remove name="PanelScheduler" />
<remove name="ScriptModule" />
<remove name="FormsAuthentication" />
<add name="DotNetServiceCasClient" type="DotNetCasClient.CasAuthenticationModule,DotNetServiceCasClient" />
</modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="XXXX" >
<endpoint contract="XXXX" address="" binding="customBinding" bindingConfiguration="nonSsLAuthBinding" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceAuthorization serviceAuthorizationManagerType="XXXX, XXXX">
<authorizationPolicies>
<add policyType="XXXX, XXXX" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<bindingElementExtensions>
<add name="nonSslAuthTransport" type="XXXX, XXXX"/>
</bindingElementExtensions>
</extensions>
<bindings>
<customBinding>
<binding name="nonSsLAuthBinding">
<textMessageEncoding messageVersion="Soap11" />
<nonSslAuthTransport authenticationScheme="None" allowCookies="true" keepAliveEnabled="true" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>