I have a link on my website to the standard publish page generated by Visual Studio. My concern is that if anybody finds out the URL to that page, they can download my software. Sure, I could password protect the page with the link, but it still would not be protecting the download URL. Are there any ways to secure the click once upload? I have looked around, and it seems like I am stuck in this sense.
Share
Public URL is a security issue in ClickOnce Deployment. However, there is a solution for your problem if your web server has windows and .NET installed. Tell me if you have one ? I will have to come up with another workaround for Linux web server in case you have that.
Brief
Firstly, a bit of information about ClickOnce deployment. When you deploy the application, the GET requests on the server made are (assuming WebDir is the publish directory on the server)
G-1.
GET /WebDir/setup.exe(Initial download)G-2.
GET /WebDir/MyApp.Application(setup.exe -url request)G-3.
GET /WebDir/MyApp.Application(.application deployment provider URL request)G-4.
GET /WebDir/Application Files/MyApp_1_0_0_0/MyApp.exe.manifest(Application manifest request)G-5.
GET /WebDir/Application Files/MyApp_1_0_0_0/MyApp.exe.deployand other .deploy files … (Application file requests)
Implementation
Now, the solution is to intercept these file requests on the server. On IIS, you can attach a custom HTTPHandler and handle the request. On Apache, you can redirect requests to a PHP code using .htaccess files. Apart from this, you will have to generate unique identifier
uidfor client instances downloaded from the server (can be your license key) and put that in the deployment provider URL query parameters.Directory Structure
Create an
"Application"folder inside yourWebDirand restrict access to/WebDir/Application/. Rest everything can be there inside/WebDir/File Requests
So here’s what you do on a Apache web server hosted on a windows machine:
/WebDir/Download.phpDownload.php, you have to sendsetup.exefrom your code (can do it withreadfile()in PHP) to the user. However, the catch is bootstrapper (setup.exe) after installing will do a GET request [G-2]. Don’t forget now, that you have to validate this file request. So basically you change the"setup.exe -url"property to includeuidbefore returning the file. For eg: change it to/WebDir/uid/MyApp.Application[G-2]. You can use MsiStuff.exe to change the URL property for the bootstrapper..htaccessfile, rewrite [G-2] to/WebDir/Handler.php?user=uid. FromHandler.php, you can check if it is a validuid. If it is valid, you will have to include theuidin the deployment provider URL and "Dependent Assemblies Path" in deployment manifest so that if an upgrade request comes (It essentially requests the deployment manifest), you can validate the user there too. Adduidto query string parameters. For eg: change it to/WebDir/MyApp.application?user=uid[G-3]. Don’t forget that you will have to resign the manifests once you modify them. Use Mage or write your own code to do that.So finally, the GET requests on the server will be (assuming
uid=1f3rd)G-1.
GET /WebDir/Download.phpAction: return
setup.exewith the -url changedG-2.
GET /WebDir/Application/setup.exe/1f3rd/MyApp.ApplicationAction: redirect, validate user, change URL, re-sign and return file
G-3.
GET /WebDir/Application/setup.exe/MyApp.Application?user=1f3rdAction: redirect, validate user and return file
G-4.
GET /WebDir/Application/1f3rd/Application Files/MyApp_1_0_0_0/MyApp.exe.manifestAction: redirect, validate user and return file
G-5.
GET /WebDir/Application/1f3rd/Application Files/MyApp_1_0_0_0/MyApp.exe.deployand other .deploy files …
Action: redirect, validate user and return file
Pros
uidin the URL present.Cons
If you want me to make something clear or explain in detail, feel free to ask. In case you have suggestions for modification to the above, post that too.
I will write a detailed CodeProject article if I have spare time someday.