Hide/Encrypt WCF Client End Points in app.config - c#

I have made a WPF application, and i am using multiple WCF services(deployed on remote server) in it. Currently all client configurations(end points) are given in app.config. If i open App.exe file (File Type: XML Configuration File) in notepad then i can see all configurations (end points) there.
What i want is that i want to hide that configurations so that end user can't see my configuration details (especially Address attribute).
Does Somebody know how to secure/hide my WCF end point? Either i need to use some tool to encrypt app.config file or i need to write client end points in code (if yes then how) ?
Thanks in Advance :)

If you're worried about divulging your endpoint address, you're doing security wrong. It sounds like what you need is--at minimum--to authenticate your WCF service properly.
I recommend starting with the WCF Security documentation.

Related

Trace / Debug app.config file reads / access operations

Is there a mechanism (or config file setting) that will trace read operations against a .NET config file?
Background: I'm working on a SOAP test client application and there's one point where it's complaining about not finding the endpoint element and contract details in the configuration file. There are 9 services, 8 are working fine. The naming of the problem service is complicated with spelling errors (service name, wsdl port name...) I'm starting to suspect that parts of the .NET framework use convention rather than direct configuration to locating parts of the binding configuration. I think I have the name mutated correctly in the various places but when making the connection it still errors.
After all that, what would help is if I could get a trace output as the program (framework) reads through the configuration file. It would be easy at that point to see what specifically is miss-spelled or where it is my mistake.
It's almost impossible to search for this topic, all the hits along the lines of "debugging config file" return links for adding logging to a config file or configuration management of an app build.

How to encrypt app.config ( Without decrypt method )

I want to encrypt my "ConnectionString" settings which is located in app.config.
But at the Runtime, I want to use( read ConnectionString ) it directly, without decrypt it.
I mean, I don't want to anyone to decrypt the string. There should be NO decryption method.
I'm thinking; it should be like embed .net/asp.net/iis feature to use.
Like "Windows Login" ( you can enter it, use it, but you can't decrypt )
===
An Example Usage; You have small website with some critical data.
You have no money to buy private server,
so you are working on shared server, if the server hacked somehow,
you application and database will be stolen.
But if you put encrypted connectionstring in app.config,
This will be hard to decrpt it and see what is inside in Database.
Encrypting and decrypting configuration settings in a config file can be done from the command line using the aspnet_regiis.exe tool.
The details are described in the following MSDN article:
Encrypting and Decrypting Configuration Sections
As the tool is mainly intended to be used with Web applications, it expects the config file to be named 'web.config'. This means that you temporarily will have to rename your app.config file to web.config:
rename App.config web.config
aspnet_regiis -pef connectionStrings . -prov DataProtectionConfigurationProvider
rename web.config App.config
DPAPI might be a solution.
You can connect your usr/pwd/credentials to the machine. JGalloway knows more about this than I. JGalloway knows more about anything dotnet than I.
http://weblogs.asp.net/jgalloway/archive/2008/04/13/encrypting-passwords-in-a-net-app-config-file.aspx
If I haven't mixed things up this creates a usr/pwd combination that is bound to the very hardware of the machine. I.e. change network card and stuff might break. Also; one cannot create the usr/pwd/creds one machine and then transfer to another. In short this means that you have to do whatever you have to do on the production machine - might give you a headache if you are targeting continuous delivery.
Caveat: I haven't tried it myself. Instead I opted for a "regular" encryption. If someone got hold of my encrypted string and bytecode and reverse engineered it I would be smoked. But it was enough of security for me.

How can I debug this web service?

I have a simple web service that looks something like this:
[WebMethod]
public OrderForecastItem GetOrderForecast(int shipTo, string catalogName, bool showPricing)
{
return OrderForecastManager.GetOrderForecast(shipTo, catalogName, showPricing);
}
I'm calling it from another place in a fairly simple way:
using (OrderForecastWS.OrderForecastWS service = new OurSite.Web.Reporting.OrderForecastWS.OrderForecastWS())
{
OrderForecastItem orderForecastItems = service.GetOrderForecast(2585432, "DENTAL", false);
}
After some gymnastics to get the systems to understand that I'm talking about the same type of objects on the client and server sides (I had to open the Reference.cs file inside my Web References, delete the generated OrderForecastItem and add a link to our real OrderForecastItem), the system runs and attempts to get the item.
Unfortunately, it now bombs during the service call, claiming:
Exception There is an error in XML document (1, 1113).(InvalidOperationException)
I can go to the web service in a browser, put in the same values, and I get a seemingly valid XML response. (It looks okay to me, and I ran it through the XML parser at W3Schools, and it cleared it.)
I think the numbers in the error are supposed to be the line and character number...but the browser seems to reformat the xml document, so I can't easily see what the original (1, 1113) location is.
I don't see an easy way to intercept the response and examine it, since it seems to be blowing up as soon as it gets it.
How can I debug this?
If you control the service, you can step into it. If it is a part of your solution and hosted in VS WebDev on your local box, just F11 from Visual Studio, if service is hosted remotely (eg by IIS on other computer) run remote debugging tool on service host msdn, and then you will be able to step in to the service remotely.
By the way, you can tell Visual Studio to re-use objects from referenced libraries for types from the service: just pick configure Service Reference from service context menu and tell which libraries to re-use.
On second thought this error may happen if returned XML could not be deserialized into your business object. May happen when class is changed on either side, or you are trying to use different version of business library than service is using.
If you use Firefox, I'd recommend Firebug. You'll be able to easily view the response from the website in its original format, which might get you closer to the line and position you're looking for.

ClickOnce connection string encryption

I'm working on my first real WinForms application, and my boss has asked that I figure out a way to encrypt the connection string inside the app.config. I've read some of the suggestions in other questions about connection string encryption, and I recognize that it isn't a silver bullet answer to the security/privacy problem. We've considered writing web services to retrieve data from the database, but this is a very small project and unfortunately isn't a priority at this time.
Edit: I left out the detail that I'm working for a state institution (community college) where, because we're identifying students using a state-mandated private system ID, we need to secure the application in some form or fashion. Students may enter their network IDs to identify themselves (which we need to protect anyway as some students have restraining orders and need much of their records kept private), but many students only know their system IDs (which are always kept private).
Regardless, we'd like to get this process working in conjunction with ClickOnce deployment, but my encryption process crashes the application when I run the ClickOnce executable. Here's my encryption code (which is lifted from another question here on SO):
public static void EncryptConfigSection(string sectionName)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null)
{
if (section.IsReadOnly() == false &&
section.SectionInformation.IsProtected == false)
{
section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
section.SectionInformation.ForceSave = true;
config.Save(ConfigurationSaveMode.Full);
}
}
ConfigurationManager.RefreshSection(sectionName);
}
I'm calling this function from the Main() function in Program.cs, but I'm not sure if this is the appropriate place for it. Additionally, while this function encrypts the app.config correctly, as soon as I exit the application, the app.config decrypts. I feel like I'm missing a piece to the puzzle (or perhaps large swaths of the puzzle).
Can anyone offer me some insight into these problems? I'd like to reiterate that I recognize that web services are the end goal here, so if this is just not a solvable problem using CLickOnce, then I'm willing to suggest that we prioritize writing web services now.
Have you looked at this topic? It talks about setting up the client using DPAPI so the string is encrypted. I would still look at the web services route rather than embed a connection string, encrypted or not, into a client application. This is ESPECIALLY true if you are talking about client apps outside of your domain (ie, non-employee use).

Get original url without non-standard port (C#)

First question!
Environment
MVC, C#, AppHarbor.
Problem
I am calling an openid provider, and generating an absolute callback url based on the domain.
On my local machine, this works fine if I hit http://localhost:12345/login
Request.Url; //gives me `http://localhost:12345/callback`
However, on AppHarbor where I'm deploying, because they are using non-standard ports, even if I'm hitting it at "http://sub.example.com/login"
Request.Url; //gives me http://sub.example.com:15232/callback
And this screws up my callback, because the port number wasn't in the original source url!
I've tried
Request.Url
Request.Url.OriginalString
Request.RawUrl
All gives me "http://sub.example.com:15232/callback".
Also to clear up that this isn't a Realm issue, the error message I am getting from DotNetOpenAuth is
'http://sub.example.com:14107/accounts/openidcallback' not under realm 'http://*.example.com/'.
I don't think I've stuffed that up?
Now, I'm about to consider some hacky stuff like
preprocessor commands (#IF DEBUG THEN PUT PORT)
string replace (Request.URL.Contains("localhost"))
All of these are not 100% solutions, but I'm sick of mulling over what could be a simple property that I am missing. I have also read this but that doesn't seem to have an accepted answer (and is more about the path rather than the authority). So I'm putting it towards you guys.
Summary
So if I had http://localhost:12345/login, I need to get http://localhost:12345/callback from the Request context.
And if I had "http://sub.example.com/login", I should get "http://sub.example.com/callback", regardless of what port it is on.
Thanks! (Sleep time, will answer any questions in the morning)
This is a common problem in load balanced setups like AppHarbor's - we've provided an example workaround.
Update: A more desirable solution for many ASP.NET applications may be to set the aspnet:UseHostHeaderForRequestUrl appSetting to true. We (AppHarbor) have seen several customers experience issues using it with their WCF apps, which is why we haven't enabled it by default and stil recommend the above solution for those situations. You can configure it using AppHarbor's "Configuration Variables" to inject the appsettings when deployed. More information can be found in this article.
I recently ran into an issue where I compared a URL to the current URL, and then highlighted navigation based on that. It worked locally, but not in production.
I had http://example.com/path/to/file.aspx as my file, but when viewing that file and running Request.Url.ToString() it produced https://example.com:81/path/to/file.aspx in a load balanced production environment.
Now I am using Request.Url.AbsolutePath to just give me /path/to/file.aspx, thus ignoring the schema, hostname, and port numbers.
When I need to compare it to the URL on each navigation item I used:
New Uri(theLink.Href).AbsolutePath
My initial thoughts are get the referrer variable and check if that includes a port, if so use it otherwise don't.
If that’s not an option because a proxy might remove the referrer header variable then you might need to use some client side script to get the location and pass it back to the server.
I'm guessing that AppHarbor use port forwarding to the IIS server so even though publicly the site is on port 80 IIS has it hosted on another port so it can't know what port the client connected on.
Something like
String port = Request.ServerVariables["SERVER_PORT"] == "80" ? "" : ":" + Request.ServerVariables["SERVER_PORT"];
String virtualRoot = Url.Content("~/");
destinationUrl = String.Format("http://{0}{1}{2}", Request.ServerVariables["SERVER_NAME"], port + virtualRoot, "/callback");
If you use the UrlBuilder class in the framework you can easly get around this. On the builder class if you set the port to -1 then the port number will be removed:
new UriBuilder("http://sub.example.com:15232/callback"){ Port = -1}
returns : http://sub.example.com/callback
To keep the port number on a local machine just check Request.IsLocal and don't apply -1 to the port.
I would wrap this into a extension method to keep it clean.
I see that this is an old thread. I had this issue running MVC5, on IIS 7.5, with an Apache proxy in front. Outside of the server, I would get "Empty Response", since the asp.net app gets the Url from apache with the custom port.
In order to have the app redirect to a subpath without including the "custom" port, forget the Response/Request objects, and use the Transfer method. For instance, if I want that users are automatically redirected to the login page in case they are not logged already:
if (!User.Identity.IsAuthenticated)
Server.TransferRequest("Account/Login");

Categories

Resources