We're in the process of developing a WCF REST web service which just receives a bunch of arbitrary text from any anonymous user and then performs some processing on the back end.
For example, here's one method from our web service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class MyRESTService : IMyRESTService
{
[WebInvoke(Method = "PUT", UriTemplate = "/MyRESTMethod?paramA={paramA}¶mB={paramB}")]
public Stream MyRESTMethod(string paramA, string paramB, Stream rawData)
{
//do some stuff...
}
}
If we just use the default IIS settings we get a (401) Unauthorized. However, after much trial and error we figured out that we could get it to work by giving WRITE access to 'Everyone' on the actual .svc file for our service.
My question is: why in the world would IIS need to have WRITE access to an .svc file for this to work? Is there a better way or am I stuck with this hackish (and possibly insecure) workaround?
WTF Microsoft?
Possibly related:
PUT and DELETE in RESTful WCF Service cause 401 Unauthorized error
IIS7 Post/Put/Patch/Delete WCF oData - Authentication Failure 401.3
I have also found this can be fixed by putting
<authentication mode="None" /> inside of <system.web> in your web.config
After talking to a tech representative from M$ I was informed that this is indeed the expected behavior. The service must have write access enabled for someone to send a request to it, and when you do this it will actually set write access automatically on the .SVC file as well.
Related
I have an N-Tier app which built as follows:
On the server side in IIS7 is sitting an ASP.Net Application that exposes methods on a WCF Service. Those methods talk to the DB using EF4. Clients written in Silverlight 4.0 are calling the methods on the WCF service.
The WCF Service exposes this method :
[OperationContract]
void DeleteItem(int i_ItemId);
I am new to seuring WCF services, but I think these next observations are true (correct me if I am wrong):
1) If I leave this method/service as is, anyone that knows that my service is sitting at http://www.mysite.com/myservice.svc could just open up VisualStudio, open "Add Service Reference" and start making calls to DeleteItem().
2) If I try to solve the above by remove the MEX endpoint, Calls to the service can still be made using some manual coding.
So trying to solve those two problems I started learning about some built-in security features in WCF. After a quick look I figured i can use the following binding Configuration so that a username and password are needed for making calls to the service :
<wsHttpBinding>
<binding name="RequestUserName" >
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
Trying to adopt this solution, the first thing that came to my mind was: When a user logs in the client, the client uses the user's name and password as the credentials for the WCF call. At the server-side, those credentials are validated against the DB.
The problem now, is that those credentials (userName and password) are , of course, known to the user, so he can just use them to call DeleteItem() in the ways I already mentioned.
From here I came up with two solutions :
1) Instead using userName and password as credentials, I will use a hard-coded key in the client. Scrambling the Dll's inside the XAP could prevent someone from obtaining this key.
2)When a user logs in the client, the server sends some kind of a temporary token (GUID or something), which the client can use to authenticate it's calls during this session of communication (Let's say, until the user closes the client).
My question are :
What the security level that the first solution provides and how hard you need to work in order to crack it?
If the first solution is very trivial to crack, Is there a built-in way in WCF to manage the tokens system I mention in the second solution ?
Other solutions that can feet the scope are welcomed.
I'm not sure about security level you are asking about, but I wouldn't feel confident storing username and password in XAP file, obfuscated or not.
I can describe a solution that I've implemented in production.
Basically, I secure the application with standard Forms Authentication, but I don't use the redirects like you normally would with ASP.NET, I use Authentication Web Service that ships with ASP.NET Forms Authentication. That way my login goes through Silverlight controls. My app has a user store that I authenticate the Authentication Service against.
To hook to the Authentication Service, I do this in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
AuthenticationService.Authenticating += new EventHandler<AuthenticatingEventArgs>(AuthenticationService_Authenticating);
}
void AuthenticationService_Authenticating(object sender, AuthenticatingEventArgs e)
{
try
{
bool authenticated = //Call your user store here.
e.Authenticated = authenticated;
}
catch (Exception ex)
{
e.Authenticated = false;
}
e.AuthenticationIsComplete = true;
}
You would secure the parts of the website like you would normally with forms using <authorization> element with <deny users="?">. The browser will handle all of the cookies for you. If you wanted to secure services, under Service/ folder you would deny not authenticated users to it.
This MSDN Post talks about the solution in more detail.
I have this scenario. Client requested us to have a WebService. I created a WCF Service. After we sent them our url to the web service description, client says
As it is we cannot consume a WCF
service, can you publish it a web
service?
Now i am wondering, they are asking me for a asmx... right?
Is there any way that i can "offer" my WCF service as an asmx service so i don't have to rewrite the whole thing?
my first "solution" is to have an .asmx file calling my .svc files directly... i don't know. I havent tried but i am heading on that direction.
Any ideas would be highly appreciated.
Tony
It is completely do-able. Just use an endpoint that exposes the service using basicHttpBinding or wsHttpBinding. The "file extension" of the URL doesn't make any difference to the client, only the content of the rerquest/response.
Here's a reference to another SO question:
REST / SOAP endpoints for a WCF service
It's very much possible.Follow the steps mentioned below and you'll be able to expose WCF service as ASMX endpoint.
Add new web service file (.asmx)
Now open the node of web .asmx file and delete .asmx.cs file
Once .cs file is deleted. You will find wcfasasmx.asmx file.
I have WCF class name as Service1(from the basic WCF service) and this class is present in current NameSpace. So I changed class name as mynamespace.Service1
Some changes is code as shown below-
In web.config in Tag add following code
<system.web>
<webServices>
<conformanceWarnings>
<remove name='BasicProfile1_1'/>
</conformanceWarnings>
</webServices>
</system.web>
Add following 2 attribute on interface(on servicecontract of WCF)
[WebService(Name = "Service1")]
[WebServiceBinding(Name = "Service1", ConformsTo = WsiProfiles.BasicProfile1_1, EmitConformanceClaims = true)]
Add [WebMethod] attribute on each operation contract.
[OperationContract]
[WebMethod]
string GetData(int value);
your service can now be consumed by asmx client too.
I wonder if you could help me with this. I have a .NET 3.5 WCF RESTful service that returns json. Service works fine on my local machine but when I deploy it on IIS6 I get this error: The server encountered an error processing the request. See server logs for more details.
The WebInvoke method is GET and when I try to access the service method in browser on the IIS6 machine I get a prompt that asks me to download a file (with the response of the GET request).
I'm really baffled by this as when I choose to download and open the file I see the json that is suppossed to be returned....Strange behavior by IIS.
Any clues on this?
The answer was rather trivial...
Because my wcf operation was returning a List of objects for some reason IIS insists in that case the BodyStyle to be WebMessageBodyStyle.Wrapped , unlike local development service where the response was returned correctly both with Bare and Wrapped formats.
Thanks for all suggestions guys.
What needs to happen to allow an HTTP POST to a WCF service?
I would like to allow people to not only use SOAP with this service, but they must also be able to HTTP POST to this service and ideally receive an XML response.
I cannot find an easy way to allow a WCF service to accept an HTTP POST.
I am past the HTTP 415 error and need some help with maybe a web.config change regarding endpoints, or an additional attribute above the method (WebInvoke).
Thank you!
In order to talk to a WCF service over the standard HTTP verbs, you need to use the WCF REST components.
In .NET 3.5 SP1, there's the WCF REST Starter Kit that you'll need (it's not part of the basic package).
When you have this, you can define an endpoint in your WCF service with a webHttpBinding and that basically should allow you to define GET, POST, PUT and DELETE operations.
Check out the WCF REST developer center for a great deal of white papers, tutorials, walk throughs and screencasts showing you exactly how to do all of this.
In a nutshell, you would adorn your service method(s) that you want to expose over HTTP REST with WebGet or WebInvoke attributes and a URL template - something like:
[ServiceContract]
public partial class YourService
{
[WebInvoke(Method = "POST", UriTemplate = "yourservice/{id}/save")]
[OperationContract]
SomeReturnType YourMethodCall(string someParam);
...
}
and then, in your web.config (for hosting in IIS) or in app.config you need an endpoint with the right binding:
<endpoint name="webEndpoint"
address="...."
binding="webHttpBinding"
contract="IYourServiceContract" />
You might also need a few extra things in your config - the WCF REST dev center should go into all the details in great depth.
I am trying to write a WCF service as a proxy for my Silverlight control to do cross-domain requests to an internet REST web service. I just want to make the requests to my service, and it would format and forward the request to the 3rd party web service (replace the hostname and part of the URL), then simply return the response to the caller.
Is my approach correct? The 3rd party server does not have the crossdomain.xml file to allow my call otherwise.
My question is, given my WCF service approach, I would like to rewrite the response body in my service with the response body I retrieved from the 3rd party service, and if possible, rewrite the response header to also be the one I got from that service. This way it minimizes the translation that my web service has to do on the response. Is it possible for me to do this rewrite? if so, how? if not, what are the best practices to implement this?
My interface is right now very primitive, something like this, simply because i don't need anything more than this. The response from the 3rd party service is a JSON response.
[ServiceContract]
interface IMyProxy
{
[OperationContract]
[WebGet(UriTemplate = "relay/{requestOptions}")]
string ForwardRequest(string requestOptions);
}
p.s. I do not need it to work with HTTPS, so no need to worry about the man-in-the-middle issue.
I figured it out, I believe (WebOperationContext).
I am still having an issue that if I duplicate the "Transfer-encoding" of the 3rd part service in my reply, I get an obscure exception down from the guts of the framework (something is "NotFound")... but that's a different story.