Connecting to WCF from K2 custom service dll with username password

  • 13 June 2011
  • 3 replies
  • 2 views

Badge +1

In K2, we have a workflow that calls a WCF service via a custom K2 smartobject service dll using a softcoded username and password in the service object code.


Currently, the username and password are exposed as service keys and entered into the smartobject service tester console when the service instance is registered.


It is a security requirement that the username and password not be exposed to the K2 administrator....or any party other than the WCF system administrator..when entered....just as we do when we enter application pool service account passwords in IIS for example!


Is there a way to mask/hide the password that is set when we register the service dll or is there a more native way to cache username and password inside K2 for the service dll to retrieve and use to connect to the WCF service?


Alternatively, we could use the K2 service account if granted the same wcf priviledges but is there a way to retrieve its password from the current context and use this to connect to the wcf?


We are using the latest K2 updated software...and have yet to figure out how to cache credentials from the help files...Any help is appreciated!


Tx


 


 


 


 


 


 


 


3 replies

Badge +5

Hi There,


It is my recommendation to manage the calling account using windows integrated authentication to the service, rather than setting credentials at the service configuration layer.


- Set the service object to impersonate mode (therefore will always make the wcf call as the calling user account).


- In your service code you can then manage which user you want to use for the functionallity the WCF service needs. I.e leave the credintials of the calling user or in your code you can revert to the app pool account.


Something like


public static class WindowsPrincipalHelper
    {
        public static WindowsImpersonationContext RevertToServiceAccount()
        {
            //revert to the user context of the service account for this part
            return WindowsIdentity.Impersonate(IntPtr.Zero);
        }


        public static void RevertToImpersonatedUser(WindowsImpersonationContext _serviceAccountContext)
        {
            if (_serviceAccountContext != null)
            {
                _serviceAccountContext.Undo();
            }
        }


        public static void RunWithServiceAccount(CodeToRunElevated secureCode)
        {
            RunWithServiceAccountPrivileges(new WaitCallback(CodeToRunElevatedWrapper), secureCode);
        }


        internal static void RunWithServiceAccountPrivileges(WaitCallback secureCode, object param)
        {
            var _serviceAccountContext = RevertToServiceAccount();
            try
            {
                secureCode(param);
            }
            finally {
                RevertToImpersonatedUser(_serviceAccountContext);
            }
        }


        private static void CodeToRunElevatedWrapper(object codeDelegate)
        {
            // Runs the codeDelegate (which is the elevated code) so that both the wrapper
            // and the codeDelegate will be executed after the usercontext has changed.
            ((CodeToRunElevated)codeDelegate)();
        }
    }


    /// <summary>
    /// Delegate for raised/lowered methods
    /// </summary>
    public delegate void CodeToRunElevated();
    public delegate void WaitCallback(object codeDelegate);

Badge +11

I also use windows integrated authentication when calling WCF from a ServiceObject, that way no password is stored.  I keep the code simple, setting the context on the client for the call:


WCFClient.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials.


If you want to store the password as part of the service instance but you don't want the administrator who types it in to see it, you would probably have to encrypt it, convert to base 64, give the hex string to the admin to type in, and then inside your ServiceObject code you could convert back from base64, decrypt, and use it.  This would be less secure.


Using windows credentials is more secure if the admin doesn't also have the password to the service account.

Badge +1

We have resolved the task as follows from your suggestions:
 
1. Modify the custom service dll to use "CredentialCache.DefaultNetworkCredentials;"
    instead of "System.Net.NetworkCredential(ClientUserName, ClientPassword, ClientDomain);"


2. Register the custom service dll instance using smartobject tester with the following setting:
    Authentication Mode: ServiceAccount (Default was Impersonate)


3.  The K2 service account, that runs the K2 blackpearl Server Service, is granted access to calls inside the WCF Service.


4. The custom service dll instance called from K2 blackpearl Server Service connects to the external wcf service using the K2 service account


    credentials with success....thus eliminating the need for hardcoding of username/password or exposing it.


ps.  I have yet to try and set Authentication Mode to SSO/Static option...which allows us to set a username and password in non clear text...which is an alternative to using the K2 service account.


 

Reply