I have a MVC application which uses forms authentication. This application also hosts a WCF webservice (the Model). Webservice caters c# objects to the application, and same data is available as JSON when called from outside the application (browser).
Everything is working fine apart from the fact that the Webservice is not authenticating any request. Following is the what I have in web.config:
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<behaviors>
<endpointBehaviors>
<behavior name="ServiceBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJson" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<services>
<service name="Services.MyService">
<endpoint address="http://localhost:1234/MyService.svc/" binding="webHttpBinding"
bindingConfiguration="webHttpBindingWithJson"
contract="Services.IService"
behaviorConfiguration="ServiceBehavior"/>
</service>
</services>
I would like to authenticate Webservice requests:
Requests from within the application should be authenticated automatically
When Webservice is called from outside the application, users are asked to get authenticated.
Any help would be appreciated.
/D
Sounds like you need an internal endpoint that serves a wsdl for the binding in to the website (authenticated using the ASP.NET identity the website is running under) and a separate binding externally for the JSON requests that uses something like OAuth to authenticate.
Either way you're looking at two different authentication mechanisms.
Related
I have seen loads of questions about this, I've spent over a day researching and trying to fix it but I've drawn a blank.
I want to deploy a WCF service onto a server connecting with HTTPS and using basic authentication. Here is my service web.config
I am using an extremely simple Calculator as a test which has a single method which adds together two numbers.
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.0" />
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="UsernameWithTransport">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="Service">
<endpoint address="https://myserver.mydomain.co.uk/CalculatorService"
binding="wsHttpBinding"
bindingConfiguration="UsernameWithTransport"
name="BasicEndpoint"
contract="TestCalculator" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
In IIS 6.0 I have enabled basic authentication and required HTTPS.
I can browse to the .svc file and it asks for my credentials. I provide them and it displays the default page. However it says:
You have created a service.
To test this service, you will need to create a client and use it to
call the service. You can do this using the svcutil.exe tool from the
command line with the following syntax:
svcutil.exe
http://myserver.mydomain.co.uk/CalculatorService/Service.svc?wsdl
This will generate a configuration file and a code file that contains
the client class. Add the two files to your client application and use
the generated client class to call the Service. For example: ......
Basically, the issue seems to be that the path to the .wsdl is a http:// not an https:// and I don't think I understand why.
I am now trying to create a C# console application to test consuming the service. I cannot add the reference to the .svc path directly because it just goes around and around in a loop asking me for my username and password. If I add the reference to the .svc?wsdl then that did work but then invoking the service gives a "Method not allowed" because it is trying to use HTTP not HTTPS.
Hope I have expained this well enough. Thanks for any help.
You requires HTTPS but in the same time you allow WSDL only over HTTP. Change this:
<serviceMetadata httpGetEnabled="true"/>
To this:
<serviceMetadata httpsGetEnabled="true"/>
Now you will be able to access WSDL over https://..../....svc?wsdl but you will still have to authenticate because authentication is global for your deployed site.
I know that similar question was asked here :
Running SOAP and RESTful on the same URL
Hosting WCF soap and rest endpoints side by side
but didn't find an answer to my problem.
I have two custom servicehostfactories that enables Dependency Injection :
public class StructureMapSoapServiceHostFactory : ServiceHostFactory
public class StructureMapRestServiceHostFactory : WebServiceHost2Factory
The implementation details are not important here.
Then I definied two endpoints in web.config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="mexGet">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<mexHttpBinding>
<binding name="mexHttpBinding" />
</mexHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="mexGet" name="ServiceImplementation.ServiceCategory">
<endpoint address="rest"
binding="webHttpBinding"
contract="Contracts.ServiceContracts.Mobile.IServiceCategory"
behaviorConfiguration ="jsonBehavior"/>
<endpoint address="soap"
binding="basicHttpBinding"
contract="Contracts.ServiceContracts.Mobile.IServiceCategory" />
<endpoint name="mexHttpBinding"
address="mex"
binding="mexHttpBinding" bindingConfiguration="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Then I created two .svc files for each custom host factories :
ServiceCategoryRest.svc
ServiceCategorySoap.svc
I don't like it. What I would like to do is to have URL in that style :
REST : http://server:port/rest/categories/{id} which mapps to the implementation of my ServiceCategory.GetCategory(int id)
SOAP : http://server:port/soap/GetCategory?id=someId
My questions are. Do i need different svc files to activate host services ? If I need there two .svc files, how can I achieve the URI above ? I'm afraid that I should configure IIS rewriting or something but would like to avoid that.
Thanks in advance for your help.
Thomas
You can achieve what you're looking for with service routes - part of ASP.NET routing, available from ASP.NET 3.5 SP1 on up.
Check out these resources:
RESTful WCF Services with No svc file and no config
Drop the Soap: WCF, REST, and Pretty URIs in .NET 4
making a WCF REST stand-alone service exe from scratch – part 1 of 4, creating the minimal bare service
Using Routes to Compose WCF WebHttp Services
In .NET 3.5 SP1, you need to add some extra infrastructure to your web.config (web routing module etc.) - while in .NET 4, this is all already built in.
After few searches I found out that in fact I don't need two different .svc files and two different ServiceHostFactories.
I kept only the StructureMapRestServiceHostFactory : WebServiceHost2Factory and ServiceCategoryRest.svc which handles well requests in REST mode and call in RPC-SOAP mode.
So if you want to run side by side the REST and the SOAP you can do it only with WebServiceHost2Factory.
If then you want to get rid of the .svc part from the URL, please read the Rick Strahl post west-wind.com/weblog/posts/570695.aspx.
I've set up a WCF service to require NTLM authentication using the following configuration:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="BinarySecurityBinding">
<binaryMessageEncoding/>
<httpTransport authenticationScheme="Ntlm"/>
</binding>
</customBinding>
</bindings>
<services>
<service name="Services.LogisticsServices" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="customBinding" bindingConfiguration="BinarySecurityBinding" contract="Services.ILogisticsServices" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I did this so that the applications that consume the web service are forced to log in because all my service's operations use impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
In IIS 7 I've enabled anonymous and Windows authentication.
When I visit http://test.server/LogisticsServices.svc, which hosts the service described above, I can see the default service description page anonymously. However, when Visual Studio tries to access http://test.server/LogisticsServices.svc/$metadata to generate a client proxy, the server is responding with HTTP code 401 and expecting authentication. Not only would I've expected the metadata to be available anonymously, but additionally, the server is not accepting the credentials I am giving it (even though, I know for a fact that they are correct).
Testing different configuration, I tried removing the authenticationScheme from my binding's transport, just to be able to generate the client proxy, but that results in an exception because the service's operations require impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
What am I missing in my service's configuration that would make the service's metadata available anonymously? I'm also open to suggestions if I'm approaching the whole thing wrong.
here is a similar discussion:
Getting an Security setting exception while accessing a WCF service
One way around this is not to use the autogenerated proxies.
In cases where we have control over both the server and the client we have found that it is much more productive to avoid using the autgenerated proxies.
A screencast of how to do this can be found here: http://www.dnrtv.com/default.aspx?showNum=122
You could try imperative instead of declarative model, see: http://msdn.microsoft.com/en-us/library/ms730088.aspx
I have a asp.net 2.0 web site with WCF service hosted inside it running on .NET 3.5 framework. The website is setup with Integrated Windows Authentication only. The web server is IIS 6 with load balancing on Windows 2003 Sp2 (2 servers). I am unable to access the WCF service (.svc) using the full url (http://myqa2.abcdefg.com/trxn/WCFTrxnService.svc). Also note that the server is configured with multiple host headers. The website is protected by siteminder. Initially I was getting an error
This collection already contains an address with scheme http. There can be at most one address per scheme in this collection. Parameter name: item
So added the following config entry
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<clear/>
<add prefix="http://myqa2.abcdefg.com"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
That error went away, but now I am being prompted for login by the browser. For same website, I am able to access .aspx page. The login prompt is appearing only for .svc file.
Here is the binding / endpoint from config file that I am using.
<system.serviceModel>
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<clear/>
<add prefix="http://myqa2.abcdefg.com"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<bindings>
<basicHttpBinding>
<binding name="IISIntegratedAuthBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="TestWCFFromSL.Web.WCFTrxnServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://myqa2.abcdefg.com/fmc/WCFNotesService.svc"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="TestWCFFromSL.Web.WCFTrxnService" behaviorConfiguration="TestWCFFromSL.Web.WCFTrxnServiceBehavior">
<endpoint
address="http://myqa2.abcdefg.com/trxn/WCFTrxnService.svc"
binding="basicHttpBinding"
bindingConfiguration="IISIntegratedAuthBinding"
contract="TestWCFFromSL.Web.IWCFTrxnService" />
</service>
</services>
<!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>-->
if a website is protected by SiteMinder, WCF / SOAP calls don't work. But a different solution to this problem is working.
The URL myqa2.abcdefg.com/trxn/WCFTrxnService.svc is protected by SiteMinder, but
myqa2/trxn/WCFTrxnService.svc is not protected by siteminder, Looks like SiteMinder only protects FQDN (Fully Qualified Domain Names). So I configured the application to call WCF service using short url instead FQDN. I also had to use crossdomainpolicy because the application considers myqa2.abcdefg.com and myqa2 as 2 seperate domains.
We are using AJAX Cascading dropdown and AutoComplete functionality with Restful WebService Services providing data. With one endpoint(non-secured) eveything was working fine, until we tried same web page with https. Our Webappplication needs to support both. Our of very few articiles/blogs on this issue I found 2 which applies to my requirements.
http://blog.abstractlabs.net/2009/02/ajax-wcf-services-and-httphttps.html
http://www.mydotnetworld.com/post/2008/10/18/Use-a-WCF-Service-with-HTTP-and-HTTPS-in-C.aspx
I followed same pattern, added 2 endpoints, assuming WCF will pickup appropriate endpoint looking at HTTP or HTTPS protocol. Worked like a charm in my dev machine(XP-IIS5) and 1 Server 2003R2(IIS6), however did work in Production server 2003-IIS6. Website in IIS is exact same(including permission etc).
The error it throws - Error 500(Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http]..)
Here's the sample configuration(ignore typos)
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="SecureBinding">
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="SearchServiceAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="SearchService">
<endpoint address="" behaviorConfiguration="SearchServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="SearchServiceContract" />
<endpoint address="" behaviorConfiguration="SearchServiceAspNetAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="SecureBinding" contract="SearchServiceContract" />
</service>
</services>
</system.serviceModel>
Any help on this is highly appreciated ?
Thanks
KSS
I'm using almost the same configuration in my service, though my endpoint behavior references <webHttp /> instead of <enableWebScript />. You mentioned your servers are the same, but in any case, have you tried testing SSL traffic elsewhere on the affected server?