none
How can I leverage on-premise domain user credentials for a remote desktop client

    Question

  • See the attached diagram.  I want to architect a solution whereby a user working on a remote PC (not on the company domain) can run a remote desktop application that authenticates the user using their on-premise active directory domain credentials.  Once authenticated, the application will use those credentials (via a token presumably) to access an on-premise WCF Rest service.

    I have a prototype working nicely which uses no authentication, however I am now exploring how best to lock down the WCF Rest service so that only authenticated users / applications can access it.

    I have configured AD FS 2.0 and created the WS-Federation Identity provider.  However what I can piece together from looking at samples and the documentation is that AD FS 2.0 will only work if the user can access the on-premise AD FS server to first authenticate and get a token, and then that token can be used to access the service bus.  That won't work in my scenario, as the user is off-site and cannot log into the domain.

    Wednesday, August 29, 2012 11:43 PM

Answers

  • Hi,

    option b: not necessary for every requst. You can use session so no authentication is required for subsequent requests from the same client. As it's a RESTful service the credential is typically put in Authorization HTTP header. However as you're probably authenticate against ACS as well you may put user credentails in HTTP body.

    As to option a it does not work.


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.







    • Edited by Allen Chen - MSFT Thursday, August 30, 2012 5:59 AM
    • Proposed as answer by Veerendra Kumar Thursday, August 30, 2012 9:50 AM
    • Marked as answer by Sage Gu Monday, September 10, 2012 2:07 AM
    Thursday, August 30, 2012 5:42 AM

All replies

  • Hi,

    Is my understanding correct that the problem you encounter is how the client can get a token from ADFS 2.0? Actually the ADFS 2.0 has several authentication types. You said it does not work is because ADFS 2.0 default uses Integrated Windows authentication (IWA). As the client is not in the domain it doesn't work. You can choose other options:

    http://social.technet.microsoft.com/wiki/contents/articles/1600.aspx

    As the root question is more related to ADFS 2.0 I suggest you post in the following forum to get better support:

    http://social.msdn.microsoft.com/Forums/en-US/Geneva/threads/


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, August 30, 2012 2:02 AM
  • Thanks for the answer.  I will look into the other authentication types and post any specific ADFS questions on the other forum if needed.

    However, I am also looking for advice how best to secure the external application as shown in the diagram, ideally using the user's on-premise domain credentials (the remote location is a standalone PC not on a domain).  I am not committed to ADFS, I was just exploring it as a possible solution.

    I am committed to using the Azure service bus as a relay service to the internally hosted WCF service.  I have this working nicely, but now I want to authenticate users and ensure only authenticated users can access the WCF service.  I want to use an authentication mechanism provided by the platform (Azure / Windows / Active directory), rather than create my own.

    Thursday, August 30, 2012 3:02 AM
  • Hi,

    Your existing way is fine. WCF is the RP that has trust relationship with ACS. ACS has trust relationship with ADFS 2.0. The client gets a token from ADFS 2.0 first and sends it to ACS. Then get ACS token and send it to WCF for authentication/authorization. It's a typical federation. But if it's not needed (in cases that you don't need another claims mapping layer in the solution) you may not use ACS. The WCF can trust the ADFS 2.0 directly. Users get token from ADFS 2.0 and directly send token to WCF.

    Considering the WCF service and the ADFS is in the same domain another solution (without federation) is, the client passes domain domain name&password to the WCF RESTful service (please make sure you're using HTTPS). Then WCF service either authenticates against AD or impersonate using client's domain name&password. The code executed during impersonation will use impersonated credential to access resource so you'll be ensured right user access right resource.


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.











    Thursday, August 30, 2012 4:10 AM
  • Thanks for the advice.  Glad to have my thinking verified.  

    Your second alternative of passing the domain username/password confirms what I was thinking of doing if I couldn't get an ADFS based solution working.  However I am wondering what the best approach to implementing that might be, is it one of the following? :

    a) Use the ClientCredentials.UserName.UserName / password on the client proxy for every request?  But then how does the WCF service extract those credentials and authenticate against AD? 

    b) Inject the username / password credentials into the message header of every request, then extract the details from the header on the server side and use those to authenticate against AD.

    Another idea I had, that would still use ADFS, is to have a separate in-house WCF authentication service where the username/password are passed through, the credentials are supplied to ADFS and a SAML token generated.  The SAML token is sent back the remote client, and then subsequent calls to the REST service use the SAML token.

    Thursday, August 30, 2012 4:49 AM
  • Hi,

    option b: not necessary for every requst. You can use session so no authentication is required for subsequent requests from the same client. As it's a RESTful service the credential is typically put in Authorization HTTP header. However as you're probably authenticate against ACS as well you may put user credentails in HTTP body.

    As to option a it does not work.


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.







    • Edited by Allen Chen - MSFT Thursday, August 30, 2012 5:59 AM
    • Proposed as answer by Veerendra Kumar Thursday, August 30, 2012 9:50 AM
    • Marked as answer by Sage Gu Monday, September 10, 2012 2:07 AM
    Thursday, August 30, 2012 5:42 AM
  • Ok.  Thanks.

    I implemented a test of this approach (without the ASP.NET session but I am sure that will work), and it functions.

    This leads me to another question.  How should I best encrypt (on the client) / and decrypt the AD username and password that is being sent over the wire in the initial request that establishes the session?

    I was using Fiddler to monitor the traffic between the WPF Client application and the service (eg https://contoso.servicebus.windows.net/DataService/...) and even though it is https, I could see the username / password as plain text.  The reason this works is because Fiddler supplies a certificate as the man in the middle and my WPF client and WCF service don't realise or care that it is happening. Then fiddler as the owner of the certificate can of course decrypt the request and show it to me.

    Thursday, August 30, 2012 10:31 AM
  • Hi,

    When you send HTTPS request using HttpWebRequest the code will automatically validate server certificate against local certificate storage for you unless you explicitly notify the code that you want to check server credential yourself:

     public static class Util
        {
          
            public static void SetCertificatePolicy()
            {
                ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate;
            }

        
            private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
            {
               //here you can validate the certificate yourself and decide whether the server certificate can be trusted
                return true;
            }
        }

    //call Util.SetCertificatePolicy() before sending request to server

    The fiddler can work to get the protected data is because, as you said, it acts as a man in the middle. Fiddler uses its own certificate and this certificate is trusted by your client machine (which requires you install it to trust certificate store beforehand).

    So generally speaking it should be safe in real case. You can also add addional logic to validate the server certificate if you still worry about it.

    It's also recommended to encrypt the username/password data in app level. The client can use a public key to encrypt data and the server can use a private key to decrypt. In this way even in case someone hacks transport layer he is still unable to get the username/password and other data.


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

















    Friday, August 31, 2012 1:39 AM