Building client for Workday Server API - no documentation on security mode. RRS feed

  • Question

  • I'm implementing a client (C#) to connect to the Workday server API (Humen_Resources).
    There is no documentation on specific security mode but the server owner tells me I should use "username and certificate".
    Below is an envelope they are expecting to receive.
    Is there a way to figure out the security requirements from the attached envelope?
    How can I implement something like this in C# code? 

    Thank you.

    <?xml version="1.0" encoding="utf-8"?>
    <env:Envelope xmlns:env="" 
    			<UsernameToken xmlns="">
    			<ds:Signature xmlns:ds="">
    					<ds:CanonicalizationMethod Algorithm=""/>
    					<ds:SignatureMethod Algorithm=""/>
    					<ds:Reference URI="">
    							<ds:Transform Algorithm=""/>
    						<ds:DigestMethod Algorithm=""/>
    						<ds:X509SubjectName>CN=Test Certificate generated by Workday Studio</ds:X509SubjectName>
    		<wd:Maintain_Contact_Information_for_Person_Event_Request xmlns:wd="urn:com.workday/bsvc" wd:Add_Only="true" wd:version="v32.2">
    					<wd:Comment>This is a comment</wd:Comment>
                            <wd:ID wd:type="Contingent_Worker_ID">abcdef</wd:ID> 

    Monday, September 9, 2019 1:41 AM

All replies

  • Hi,

    As far as I know, this tripartite service is consumed through WSE3.0, and there are no native bindings in WCF to build clients.
    If you need to sign the message, you need to provide a certificate on the client, and if you need a user name, you need to set up the client to provide a username / password. 
    However, only one of these two authentication methods is needed to identify the client.
    Please refer to the below link, wish it is useful to you.

    Feel free to let me know if there is anything I can help with.
    Best Regards

    Monday, September 9, 2019 9:42 AM
  • Hi Abraham,

    Thank you for the answer. After researching all these links here is my code that works:

    public Human_ResourcesPortClient GetWebServiceClient()
                var serviceCert = GetInstalledCert2("‎983569e4070beb9a757bd3a5918e255bdd461418");
                var signCert = GetInstalledCert2("‎62115aa04de10f9fc58500a05a52673954eca3b7");
                SecurityBindingElement sbe = SecurityBindingElement.CreateUserNameForCertificateBindingElement(); 
                sbe.IncludeTimestamp = false;
                sbe.EnableUnsecuredResponse = true;
                sbe.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
                const int lim = Int32.MaxValue;
                var timeout = TimeSpan.FromMinutes(2);
                TextMessageEncodingBindingElement tmebe = new TextMessageEncodingBindingElement(
                tmebe.ReaderQuotas.MaxDepth = lim;
                tmebe.ReaderQuotas.MaxStringContentLength = lim;
                tmebe.ReaderQuotas.MaxArrayLength = lim;
                tmebe.ReaderQuotas.MaxBytesPerRead = lim;
                tmebe.ReaderQuotas.MaxNameTableCharCount = lim;
                HttpsTransportBindingElement tbe = new HttpsTransportBindingElement
                                                            MaxBufferPoolSize = lim,
                                                            MaxReceivedMessageSize = lim,
                                                            MaxBufferSize = lim,
                                                            Realm = string.Empty
                var cb = new CustomBinding(sbe, tmebe, tbe)
                    SendTimeout = timeout,
                    ReceiveTimeout = timeout
                string certName = serviceCert.Subject.Replace("CN=", "");
                var proxy = new Human_ResourcesPortClient(
                    new EndpointAddress(new Uri(_url.Trim()), EndpointIdentity.CreateDnsIdentity(certName)) );
                proxy.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;            
                proxy.ClientCredentials.UserName.UserName = _username;
                proxy.ClientCredentials.UserName.Password = _password;
                proxy.ClientCredentials.ClientCertificate.Certificate = signCert;
                proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = serviceCert;
                return proxy;

    Paul S.

    Monday, September 16, 2019 11:21 PM
  • can you please share how did you get installed certificate ?

    Friday, October 16, 2020 3:06 PM
  • private static X509Certificate2 GetInstalledCert2(string thumbprint)
                X509Certificate2 ret = null;
                X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                X509Certificate2Collection certificates = store.Certificates;
                foreach (X509Certificate2 c in certificates)
                    if (c.Thumbprint.Equals(thumbprint, StringComparison.InvariantCultureIgnoreCase))
                        ret = c;
                return ret;

    Paul S.

    Friday, October 16, 2020 3:18 PM
  • Thank you very much Paul for your quick response.

    can you please tell me how did you get those id from ? What is the process to generate it.

    Thank you 


    Friday, October 16, 2020 4:12 PM
  • Open certificate in the certificate manager.

    In "Details" tab find a Thumbprint.

    That is the ID I used for finding a certificate. You can put it into the configuration.

    Paul S.

    Friday, October 16, 2020 4:33 PM
  • Thank you Paul. What are those 2 different key. I see its different in your case one is  for Certificate and sign 


    Monday, October 19, 2020 4:24 PM