How to use Windows Authentication in WPF? - wpf

I'm not finding much documentation on how to use Windows Authentication in a WPF app. I wouldn't have thought that it would be any different than in any non-WPF app, but it seems that it is. I want to go into my project Properties -> Application and ensure that Windows Authentication is on, but that option is not available in a WPF app (as the following document confirms).
http://msdn.microsoft.com/en-us/library/tzdks800.aspx
If I ignore all that and just look at My.User.Name (VB), it is empty. This tells me that somehow Windows Authentication is not enabled.
Seems like there is a concept I am missing; could someone point me in the right direction?
My plan is to use PrincipalPermissionAttribute to restrict access to certain parts of my app (or perhaps the entire app, by applying it to Application_Startup()).

Itowlson's answer is correct, but also, in order to use the PrincipalPermissionAttribute on any method, you have to first make the windows principal the current principal by calling:
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)

The reason this doesn't work in WPF is that these services are implemented in VB's WindowsFormsApplicationBase class, which isn't used in WPF applications. To do the same thing yourself:
Call WindowsIdentity.GetCurrent() to get the Windows user identity. You can get the name from this.
If you specifically want to set the thread principal the way the VB Windows Authentication option does, call Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()) -- this is exactly what WindowsFormsApplicationBase does internally.
EDIT: If you prefer the My.User API, it looks like you should be able to do the same thing by calling My.User.InitializeWithWindowsUser(). I haven't tested this though.

Related

Global Settings & Commands - OO Design Patterns

I am currently building a WPF application and have some system wide settings. Where is the best place to store these settings? App.Config file, Database or some other sort of XML file? (need to read and write).
My other issue is the application has two states (i.e. Admin Mode, Client Mode) and depending on the state the application behaves differently i.e. (Shut Down, Restart, Lock, Unlock etc.) This seems like a good case to implement the State design pattern... but the issue I am facing is that the running application is itself the context class. I am a bit confused... should I be implementing the Singleton Pattern? How is this best implemented?
In general it is often easiest to store application settings using the Settings page of the Project Designer in Visual Studio. These settings can either be stored per user or per application. Either way, they can be saved easily by calling:
Properties.Settings.Default.Save();
They can be accessed similarly:
Properties.Settings.Default.FirstUserSetting = "abc";
You can find out full details by taking a look at the Managing Application Settings page on MSDN.
Regarding your second question, I would recommend using the State Design Pattern. Unfortunately, I didn't understand your problem with that, so please let me know what your issue is and I will try to address it.

WCF ServiceHost restricted user netsh/httpcfg

I use a self hosted service within a WPF application for certain tasks. The service host is started at runtime and its base address is http://localhost:Whatever-port-is-free-at-runtime. This works fine when the user has admin rights but problems arise when the application is ran by a restricted user.
I found some suggestions on the web that suggested reserving the url using netsh/httpcfg which works fine for admin users but fails for restricted users because they presumably do not have the rights to use these tools to reserve a url. As the port number is not known until runtime the url reservation command can logically only be run at runtime which means the process will be initiated by a restricted user without the right privilege to execute the command. Am i correct in thinking this?
What i would like to know is if there is a suitable work around? Also, i would like to know if a restricted user can open a locally hosted WCF service at all, since solving the aforementioned problem will be pointless if the restricted user couldn't do this.
This question perfectly describes my first issue of URL reservation
In WCF, the HTTP and HTTPS bindings use HTTP.sys under the cover to reserve a required URL for a specific WCF service, which is the same path IIS itself follows while doing the bindings for the websites it manages. This explains why the process performing the HTTP/HTTPS binding is required to run in elevated mode.
That being said, I would solve your issue in two different ways:
Option 1: use a different kind of binding. NetTcpBinding and NetNamedPipesBinding, for example, do not generally require administrative privileges: this is by far the easiest way to go.
Option 2: setup the required namespace reservation at installation time. This way you may ask your users to perform the installation in elevated mode and later allow restricted accounts to run it. While performing the initial installation/reservation you may also find out an available port to use (and perhaps save it in a configuration file for later reuse).

Does Silverlight 4's WriteableBitmap *really* cripple legit cross-domain access in the name of DRM?

In this thread from a year ago it's explained that WriteableBitmap will block read access when any part of it comes from an outside domain - say a free image server.
It's further elaborated upon that this is for "DRM". I guess there's some big threat of someone writing a movie-ripper in Silverlight that includes a movie from another domain and then re-captures it... except for the realization you can just rewrite the bloody xap as it comes down the wire and then it's same-domain! But that's neither here nor there.
Anyway, obviously I'm trying to use WritableBitmap to export a screenshot of the user's current setup; but I'm stopped by this cross-domain issue.
Is there really no supported way to do this in the latest version of Silverlight? No crossdomain.xml or clientaccesspolicy.xml? Isn't this crippling for Silverlight - a giant "Screw You", putting half-hearted security roadblocks in that impede developers but don't stop attackers?
Edit: This question is identical to this question here.
Your sentiment is shared by many, many devs trying to do this for legit purposes. There are some work-arounds out there, all of them either hacky or bizarro. But this is probably the best one I've seen: Screen Capture in SIlverlight 4.0.
Just read again and saw that you're not looking for a crossdomain.xml solution. This page has some other options (again, no solution out there is "great"): http://betaforums.silverlight.net/forums/t/118030.aspx
Also, not sure if this is an option, but your app as an OOB app will not be restricted to security checks in ClientAccessPolicy.xml or CrossDomain.xml. Is Out-of-Browser an option for you?
EDIT:
Upon further review of the post and comments, I believe (Tom, please confirm this) that the need isn't to get a screenshot of the user's instance of the SL app running on their own box (which something like Customer Support in Silverlight would take care of pretty well).
Rather, it is to take picture of the user's screen (same as PrtSc-ish). In this case, it is a lot tougher, but not impossible. Rui show's how he does it here, but it relies on a component already being on a user's machine. Jeremy get's even more creative with Silverlight 4 Hack: Use Native/Desktop CLR Without COM Registration, which would effectively allow access.
This WritableBitmap behavior have nothing to do with DRM and everything to do with security. If the screenshot you trying to take shows image element with content from different domain then that domain must have crossdomain.xml file with appropriate permissions. You can contact domain owner and ask them to place crossromain.xml in the root of their domain.
Alternatively, Full-Trust OOB application should do the trick since it doesn't check for crossdomain.xml.
Ok, If you have <Image Source="http://crossdomain.com/someimage.jpg" /> in your visual tree and you try to create WriteableBitmap from it, that WriteableBitmap's pixel access will be locked, crossdomain.xml or not. (Shame on you microsoft). Good news (sorta) is, you can use following workaround: Load image using WebClient; call SetSource on image with stream from OpenReadCompleted handler. Create your WriteableBitmap and notice how Pixels property doesn't throw security exception anymore. Far from ideal, but manageable.
As explained in the identical question the only way to get silverlight to allow you to get the content out of a Writeable Bitmap without any of the following:
Out-of-browser
Service/Code/App/Rooted GAC otherwise installed on the user's Machine
Elevated Trust
is to proxy the content and trick silverlight into thinking it's all from the same domain.

Getting hold of a Silverlight Out of Browser Application Id

I'm trying to launch a SL4 OOB application from the web browser. I'm currently trying to achieve this by associating a file type with sllauncher.exe and then adding the SL4 OOB application id as a parameter. The SL4 OOB application is launched when the specific file type is downloaded from the browser, but in order for me to create an installer I need to be able to retrieve the application id so I can update the registry entry for the file type association.Does anyone know how the application id is generated or if it's possible to force a specific application id to be used?
I fear that this won't be easy...
There's a method Deployment.GetAppIdForUri which sounds like it does exactly what you need, but unfortunately it is marked SecurityCritical so you can't use it.
A hack that might work is this:
When the app is installed OOB, you might use Application.Current.Host.Source or something like that plus a bit of substring magic to get the app ID. Unfortunately, I'm not able to test that right now because I'm uninstalling the VS2010 RC on this machine right now ;-)
Anyway, if that works, you might take the ID and write it into IsoStore for later use.
Forcing a specific ID for the app would be nice, but I think it's not possible.
Cheers, Alex
The shortcut file of Silverlight OOB application includes the application id. Retrieving the application id from the shortcut file is work to me.

Can Silverlight (SLOOB) start a process even with full trust?

I have been tasked with writing an installer with a silverlight out of browser application. I need to.
get the version off a local EXE
check a web service to see that it is the most recent version
download a zip if not
unpack the zip
overwrite the old EXE
start the EXE
This installer app is written in .NET WinForms now but the .NET framework is an obstacle for people to download.
The recommended solution is to use a SLOOB however i am not sure how to assign full trust. If i assign full trust can I start a process.
Thanks
Looking into this, I suspect you're going to have to create the process using WMI through the COM interface. At the end of the day, that makes this a very difficult option and very subject to failure due to a host of reasons (WMI being disabled or secured, user won't give full trust, etc.) I suspect you would be much better off creating a .msi deployment package or something similar that was able to go out and download the framework, if necessary. There are a lot of deployment models available, almost all of which feel superior to this one.
That said, if you're going to do this:
To get the COM object, you're going to want to use the AutomationFactory.CreateObject(...) API. Tim Heuer provides a sample here.
To actually do the WMI scripting, you're going to want to create the WbemScripting.SWbemLocator object as the root. From there, use the ConnectServer method to get a wmi service on the named machine. You can then interrogate the Win32_Process module to create new processes.
Edit: I spent a little time working on this and, even on my local machine as Admin I'm running into security problems. The correct code would be something similar to:
dynamic locatorService = AutomationFactory.CreateObject("WbemScripting.SWbemLocator");
dynamic wmiService = locatorService.ConnectServer("winmgmts:{impersonationLevel=impersonate,authentationLevel=Pkt}//./root/cimv2");
dynamic process = wmiService.Get("Win32_Process");
dynamic createParameters = process.Methods_["Create"].InParameters.SpawnInstance_;
createParameters.CommandLine = "cmd.exe";
wmiService.ExecMethod("Win32_Process", "Create", createParameters);
Silverlight 4 will have support for something like this: http://timheuer.com/blog/archive/2010/03/15/whats-new-in-silverlight-4-rc-mix10.aspx#sllauncher

Resources