none
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="http://schemas.xmlsoap.org/soap/envelope/" 
    				xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
    				xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    	<env:Header>
    		<wsse:Security>
    			<UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    				<wsse:Username>user@somedomain</wsse:Username>
    			</UsernameToken>
    			<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    				<ds:SignedInfo>
    					<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    					<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    					<ds:Reference URI="">
    						<ds:Transforms>
    							<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
    						</ds:Transforms>
    						<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
    						<ds:DigestValue>agI6c...............clE=</ds:DigestValue>
    					</ds:Reference>
    				</ds:SignedInfo>
    				<ds:SignatureValue>UvDMcgL4NZqlAqzYloL46.......U3Xkpw==
    				</ds:SignatureValue>
    				<ds:KeyInfo>
    					<ds:X509Data>
    						<ds:X509SubjectName>CN=Test Certificate generated by Workday Studio</ds:X509SubjectName>
    						<ds:X509Certificate>MIIC5zCCAc8CBgFt........wl3Y8+ForIfN/GG7yqSEmIvhSWA1z35L/pMN7
    											UCo+VU5j
    						</ds:X509Certificate>
    					</ds:X509Data>
    				</ds:KeyInfo>
    			</ds:Signature>
    		</wsse:Security>
    	</env:Header>
    	<env:Body>
    		<wd:Maintain_Contact_Information_for_Person_Event_Request xmlns:wd="urn:com.workday/bsvc" wd:Add_Only="true" wd:version="v32.2">
    			<wd:Business_Process_Parameters>
    				<wd:Auto_Complete>true</wd:Auto_Complete>
    				<wd:Run_Now>true</wd:Run_Now>
    				<wd:Comment_Data>
    					<wd:Comment>This is a comment</wd:Comment>
    					<!--<wd:Worker_Reference>
                            <wd:ID wd:type="Contingent_Worker_ID">abcdef</wd:ID> 
                        </wd:Worker_Reference>-->
    				</wd:Comment_Data>
    			</wd:Business_Process_Parameters>
    		</wd:Maintain_Contact_Information_Data>
    		</wd:Maintain_Contact_Information_for_Person_Event_Request>
    	</env:Body>
    </env:Envelope>

    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.
    https://social.msdn.microsoft.com/Forums/vstudio/en-US/38286c54-de81-41de-9557-c8fed4ca909f/encryption-signature-and-username-token?forum=wcf

    https://stackoverflow.com/questions/26251832/correct-wcf-service-binding-for-signature-verification

    https://stackoverflow.com/questions/5836685/correct-way-communicate-wsse-usernametoken-for-soap-webservice

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

    Monday, September 9, 2019 9:42 AM
    Moderator
  • 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(
                                                                    MessageVersion.Soap11,
                                                                    Encoding.UTF8);
                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(
                    cb,
                    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);
                store.Open(OpenFlags.ReadOnly);
                X509Certificate2Collection certificates = store.Certificates;
    
                foreach (X509Certificate2 c in certificates)
                {
                    if (c.Thumbprint.Equals(thumbprint, StringComparison.InvariantCultureIgnoreCase))
                    {
                        ret = c;
                        break;
                    }
                }                       
                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 

    Hardik

    Friday, October 16, 2020 4:12 PM
  • Open certificate in the certificate manager. 
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-view-certificates-with-the-mmc-snap-in

    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 

    -Hardik

    Monday, October 19, 2020 4:24 PM