I have had a wet dream for a long time, about implementing WIF/Claimsbased authentication into Windows Credential Provider/Remote Desktop. I don’t really care weather it could be though the RDP Website and/or directly on the Windows Server.
If we want to implement claims based authentication in corporation with remote desktop we need to consider what scenario this makes sense for, and how the logon process should be. Doing passive authentication in a browser, the user gets redirected to an identity provider and validated, has a SAML token issued and posted back to the website. Validation at the Identity Provider could also involve redirecting the user to yet another Identity provider (Microsoft Azure ACS, another ADFS 2.0 server, Google ID, Facebook and such) and the all this without the original website knowing anything about this, all it cares about is getting a SAML token from its trusted Identity Provider.
Doing Active Federation, lets say, from a Windows Application, we (could) ask the user how he wants to be validated and then though Kerberos, Certificates or Username/Password send the users credentials to the Identity Provider on behalf of the user and get’s back a SAML token. If the user want to logon though Windows Live ID in this scenario, we first need to ask the user for he's username/password ( this is where all alarm bells should go off for most security aware users ) and send this to login.live.com and by some kind of magic we get back a SAML token. We then ask out local Identity provider to Authorize us, using the SAML token from Windows Live ID and get back a SAML token and can continue the login process.
First of all, asking a user to type in a username and password for Facebook/windows Live ID/what ever on a “proprietary login page” is not good practice. Next, I doubt Microsoft/Facebook/whatever is allowing validating username and passwords though any kind of API, so the above will not work in any case.
So why is this even interesting, if its wrong ? Imaging the most common setup. Company A and Company B wants to collaborate and allow each other users access to certain resources. Instead of creating an Active Directory trust, Company A and B both install ADFS 2.0 and created a mutual trust between these. Now they can both add users to each others SharePoint 2010 and other Claims aware web applications. But what if they want to grant access to Microsoft CRM 2011, create Exchange mailbox's, allow access to Axapta 2009/2012 or use any other kind of application that rely on a Windows user in the Active Directory, then they need to map the User Principal name to locally created Active Directory users. How you do that, is beyond the scope of this post, but its doable and used many places.
Now image you want to allow users from Company A to access Company B’s Citrix XenApp or Remote Desktop servers. So User1 from Company A also have a User account in Company B, but he doesn’t know the password for that account. To give the whole Single Sing-on experience all he needs to know is the username and password to he’s own AD account in Company A.
If you rely on Citrix XenApp you could implement the solution explained here, but that will not work with Remote Desktop. The solution explained there, will not work for user accessing the solution with PNAgent installed locally either ( PDA, Tablets, Thin Clients or what ever ) so an alternative solution will need to rely on replacing the Credential Provider ( called Gina pre windows vista ).
I came across this blog post and I really really wish I was better a coding C++ so I could create this my self. I can do hello world and maybe write to a text file, but this is just to much for my skillset. Google is not much help here, but you will probably come across www.pgina.org at some point.
This will not be completely what I wanted, but at least it’s a few steps in the right direction. Pgina is a cool, yet in some ways limited implementation of a Gina/Credential Provider that send events back to a Service written in .NET 4.0, you can then develop plugins that gets loaded into this service and react/modify things doing the login process. It come bundled with tons of cute add-ons that can validate users though LDAP/Radius/SQL or even IMAP/POP3 . When I say it is limited, I do that, from the perspective that it could have been nice if they had implemented support for asking for more than just username and password. a 3rd field for a passcode to do RSA Token or SMS 2 factor validation would have been a very nice touch, but for now lets just focus on Claimsbased authentication.
So just to test my theory I installed Pgina on a server and wrote a simple add-on to Pgina, that would take what ever the user types in, validate it against and Identity Provider, find the user based on the UPN claim in the local Active Directory and then log the user on.
Doing login, no matter what, it all have to end up with win logon getting a valid username and password. But in a world of claims based authentication we don’t have the password. God knows how Citrix manage to get a user logged on purely based on a Kerberos Ticket, and I would love to see this implemented in Pgina too, but a even better solution would be if someone with more brains than me, could write an Authentication Package as explained by Steve Syfuhs in he's blog post. But for now, we focus on the scenario where a user from Company A logs on to a Server inside Company B and the user have an account in the local AD with same UPN.
What I do here is validate what ever the user types in,
1) by asking for a SAML token from the remote Identity Provider.
2) If I get a token back, I extract the User Principal name and search the local Active Directory for such an user.
3) I then validate that the password the user typed is also the password the local Active Directory account, and if login fails, I reset the password and set the login password to this.
Since the context the login process run as, does not have permission to look up in the local AD and/or reset passwords, we also need to tell the PGina addon what username and password to use when talking to AD
Finally, since RDP will try to Negotiate security (the popup for credentials before you are connected) and we want PGina to handle this, you need to open Remote Desktop Session Host Configuration and set it to RDP Security Layer
And voila, we just logged on to Remote Desktop using Claims based authentication.