Sample code for 30+ languages & platforms
Delphi DLL

eHealth.gov.be RequestSecurityToken

Request a security token for use with the eHealth.gov.be SOAP web services.

Chilkat Delphi DLL Downloads

Delphi DLL
uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, XmlDSigGen, CkDateTime, HttpResponse, StringBuilder, BinData, Cert, Http, Xml;

...

procedure TForm1.Button1Click(Sender: TObject);
var
success: Boolean;
cert: HCkCert;
xmlToSign: HCkXml;
bdCert: HCkBinData;
dt: HCkDateTime;
gen: HCkXmlDSigGen;
xmlCustomKeyInfo: HCkXml;
sbXml: HCkStringBuilder;
http: HCkHttp;
url: PWideChar;
resp: HCkHttpResponse;
responseStatus: Integer;
bdSecToken: HCkBinData;

begin
success := False;

// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.

// Provide a certificate + private key.
// Note: If your certificate + private key is located on a hardware token or smartcard, you can call a different function to load from smartcard..
cert := CkCert_Create();
success := CkCert_LoadPfxFile(cert,'SSIN=12345678.acc.p12','p12_password');
if (success = False) then
  begin
    Memo1.Lines.Add(CkCert__lastErrorText(cert));
    Exit;
  end;

// Create the following XML to be signed..

// <?xml version="1.0" encoding="UTF-8"?>
// <soapenv:Envelope xmlns:ns="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
// 	<soapenv:Header>
// 		<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
// 		xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
// 			<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" 
// 			    ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" 
// 			    wsu:Id="X509-4A13D668E59AAC4F3816750824965588">{organization certificate}</wsse:BinarySecurityToken>			
// 			<wsu:Timestamp wsu:Id="TS-4A13D668E59AAC4F3816750824965567">
// 				<wsu:Created>2023-02-01T12:42:11.156Z</wsu:Created>
// 				<wsu:Expires>2023-02-01T12:58:51.156Z</wsu:Expires>
// 			</wsu:Timestamp>
// 		</wsse:Security>
// 	</soapenv:Header>
// 	<soapenv:Body wsu:Id="id-4A13D668E59AAC4F38167508249655911" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
// 		<wst:RequestSecurityToken Context="RC-302613de-a809-46b5-931a-0a55bfca5937" 
// 		    xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706"
// 		    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
// 		    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
// 		    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
// 		    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
// 		    xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
// 			<wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</wst:TokenType>
// 			<wst:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</wst:RequestType>
// 			<wst:Claims Dialect="http://docs.oasis-open.org/wsfed/authorization/200706/authclaims">
// 				<auth:ClaimType Uri="urn:be:fgov:kbo-bce:organization:cbe-number">
// 					<auth:Value>{cbenumber}</auth:Value>
// 				</auth:ClaimType>
// 				<auth:ClaimType Uri="urn:be:fgov:ehealth:1.0:certificateholder:enterprise:cbe-number">
// 					<auth:Value>{cbenumber}</auth:Value>
// 				</auth:ClaimType>
// 			</wst:Claims>
// 			<wst:Lifetime>
// 				<wsu:Created>2023-02-01T08:30:10+02:00</wsu:Created>
// 				<wsu:Expires>2023-02-01T09:30:10+02:00</wsu:Expires>
// 			</wst:Lifetime>
// 			<wst:KeyType>http://docs.oasis-open.org/ws-sx/wstrust/200512/PublicKey</wst:KeyType>
// 		</wst:RequestSecurityToken>
// 	</soapenv:Body>
// </soapenv:Envelope>

xmlToSign := CkXml_Create();
CkXml_putTag(xmlToSign,'soapenv:Envelope');
CkXml_AddAttribute(xmlToSign,'xmlns:ns','http://docs.oasis-open.org/ws-sx/ws-trust/200512');
CkXml_AddAttribute(xmlToSign,'xmlns:soapenv','http://schemas.xmlsoap.org/soap/envelope/');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Header|wsse:Security',True,'xmlns:wsse','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Header|wsse:Security',True,'xmlns:wsu','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Header|wsse:Security|wsse:BinarySecurityToken',True,'EncodingType','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Header|wsse:Security|wsse:BinarySecurityToken',True,'ValueType','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Header|wsse:Security|wsse:BinarySecurityToken',True,'wsu:Id','X509-4A13D668E59AAC4F3816750824965588');

bdCert := CkBinData_Create();
CkCert_ExportCertDerBd(cert,bdCert);
CkXml_UpdateChildContent(xmlToSign,'soapenv:Header|wsse:Security|wsse:BinarySecurityToken',CkBinData__getEncoded(bdCert,'base64'));

CkXml_UpdateAttrAt(xmlToSign,'soapenv:Header|wsse:Security|wsu:Timestamp',True,'wsu:Id','TS-4A13D668E59AAC4F3816750824965567');

dt := CkDateTime_Create();
CkDateTime_SetFromCurrentSystemTime(dt);
CkXml_UpdateChildContent(xmlToSign,'soapenv:Header|wsse:Security|wsu:Timestamp|wsu:Created',CkDateTime__getAsTimestamp(dt,False));
CkDateTime_AddSeconds(dt,300);
CkXml_UpdateChildContent(xmlToSign,'soapenv:Header|wsse:Security|wsu:Timestamp|wsu:Expires',CkDateTime__getAsTimestamp(dt,False));
CkDateTime_AddSeconds(dt,-300);

CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body',True,'wsu:Id','id-4A13D668E59AAC4F38167508249655911');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body',True,'xmlns:wsu','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'Context','RC-302613de-a809-46b5-931a-0a55bfca5937');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'xmlns:auth','http://docs.oasis-open.org/wsfed/authorization/200706');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'xmlns:ds','http://www.w3.org/2000/09/xmldsig#');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'xmlns:wsa','http://schemas.xmlsoap.org/ws/2004/08/addressing');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'xmlns:wsp','http://schemas.xmlsoap.org/ws/2004/09/policy');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'xmlns:wsse','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd');
CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken',True,'xmlns:wst','http://docs.oasis-open.org/ws-sx/ws-trust/200512');
CkXml_UpdateChildContent(xmlToSign,'soapenv:Body|wst:RequestSecurityToken|wst:TokenType','http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1');
CkXml_UpdateChildContent(xmlToSign,'soapenv:Body|wst:RequestSecurityToken|wst:RequestType','http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue');

success := CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken|wst:Claims',True,'Dialect','http://docs.oasis-open.org/wsfed/authorization/200706/authclaims');
success := CkXml_UpdateAttrAt(xmlToSign,'soapenv:Body|wst:RequestSecurityToken|wst:Claims|auth:ClaimType[1]',True,'Uri','urn:be:fgov:ehealth:1.0:certificateholder:person:ssin');

CkXml_UpdateChildContent(xmlToSign,'soapenv:Body|wst:RequestSecurityToken|wst:KeyType','http://docs.oasis-open.org/ws-sx/wstrust/200512/PublicKey');

gen := CkXmlDSigGen_Create();

CkXmlDSigGen_putSigLocation(gen,'soapenv:Envelope|soapenv:Header|wsse:Security|wsse:BinarySecurityToken');
CkXmlDSigGen_putSigLocationMod(gen,1);
CkXmlDSigGen_putSigId(gen,'SIG-4A13D668E59AAC4F38167508249656212');
CkXmlDSigGen_putSigNamespacePrefix(gen,'ds');
CkXmlDSigGen_putSigNamespaceUri(gen,'http://www.w3.org/2000/09/xmldsig#');
CkXmlDSigGen_putSignedInfoPrefixList(gen,'soapenv urn urn1');
CkXmlDSigGen_putIncNamespacePrefix(gen,'ec');
CkXmlDSigGen_putIncNamespaceUri(gen,'http://www.w3.org/2001/10/xml-exc-c14n#');
CkXmlDSigGen_putSignedInfoCanonAlg(gen,'EXCL_C14N');
CkXmlDSigGen_putSignedInfoDigestMethod(gen,'sha256');

// Set the KeyInfoId before adding references..
CkXmlDSigGen_putKeyInfoId(gen,'KI-4A13D668E59AAC4F3816750824965589');

// -------- Reference 1 --------
CkXmlDSigGen_AddSameDocRef(gen,'TS-4A13D668E59AAC4F3816750824965567','sha256','EXCL_C14N','wsse soapenv urn urn1','');

// -------- Reference 2 --------
CkXmlDSigGen_AddSameDocRef(gen,'id-4A13D668E59AAC4F38167508249655911','sha256','EXCL_C14N','urn urn1','');

// -------- Reference 3 --------
CkXmlDSigGen_AddSameDocRef(gen,'X509-4A13D668E59AAC4F3816750824965588','sha256','EXCL_C14N','_EMPTY_','');

CkXmlDSigGen_SetX509Cert(gen,cert,True);

CkXmlDSigGen_putKeyInfoType(gen,'Custom');

// Create the custom KeyInfo XML..
xmlCustomKeyInfo := CkXml_Create();
CkXml_putTag(xmlCustomKeyInfo,'wsse:SecurityTokenReference');
CkXml_AddAttribute(xmlCustomKeyInfo,'wsu:Id','STR-4A13D668E59AAC4F38167508249655810');
CkXml_UpdateAttrAt(xmlCustomKeyInfo,'wsse:Reference',True,'URI','#X509-4A13D668E59AAC4F3816750824965588');
CkXml_UpdateAttrAt(xmlCustomKeyInfo,'wsse:Reference',True,'ValueType','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3');

CkXml_putEmitXmlDecl(xmlCustomKeyInfo,False);
CkXmlDSigGen_putCustomKeyInfoXml(gen,CkXml__getXml(xmlCustomKeyInfo));

// Load XML to be signed...
sbXml := CkStringBuilder_Create();
CkXml_GetXmlSb(xmlToSign,sbXml);

CkXmlDSigGen_putBehaviors(gen,'IndentedSignature');

// Sign the XML...
success := CkXmlDSigGen_CreateXmlDSigSb(gen,sbXml);
if (success = False) then
  begin
    Memo1.Lines.Add(CkXmlDSigGen__lastErrorText(gen));
    Exit;
  end;

// The sbXml is sent as the HTTP request body below..
Memo1.Lines.Add(CkStringBuilder__getAsString(sbXml));

// -----------------------------------------------------------------------------------------------------------
// Send the SOAP requet to ask the server to issue a security token, which can then be used to access other SOAP services..
http := CkHttp_Create();

success := CkHttp_SetSslClientCert(http,cert);
if (success = False) then
  begin
    Memo1.Lines.Add(CkHttp__lastErrorText(http));
    Exit;
  end;

CkHttp_SetRequestHeader(http,'Content-Type','text/xml');

url := 'https://services-acpt.ehealth.fgov.be/IAM/SecurityTokenService/v1/RequestSecurityToken';
resp := CkHttpResponse_Create();
success := CkHttp_HttpSb(http,'POST',url,sbXml,'utf-8','application/xml',resp);
if (success = False) then
  begin
    Memo1.Lines.Add(CkHttp__lastErrorText(http));
    Exit;
  end;

responseStatus := CkHttpResponse_getStatusCode(resp);
Memo1.Lines.Add('Response Status Code = ' + IntToStr(responseStatus));

// You'll want to check to see if the response status code = 200.
// If not, then the response body contains error information instead of a security token.
// This example will assume we received 200 status code.

Memo1.Lines.Add(CkHttpResponse__bodyStr(resp));

// The response body contains XML like this:

// <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
//     <SOAP-ENV:Header/>
//     <SOAP-ENV:Body>
//         <wst:RequestSecurityTokenResponse xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512" Context="RC-302613de-a809-46b5-931a-0a55bfca5937">
//             <wst:RequestedSecurityToken>
//                 <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="_3e8ea5c951b2167c274974750ace9b5d" 
// ...
//                 </Assertion>
//             </wst:RequestedSecurityToken>
//         </wst:RequestSecurityTokenResponse>
//     </SOAP-ENV:Body>
// </SOAP-ENV:Envelope>

// The portion of the response from  <Assertion ..> ... </Assertion>  is the SAML security token to be included
// in a subsesquent SOAP request.  It is extremely important to not modify the contents of the security token in any way, including not changing
// whitespace or any formatting.  Therefore, we get the response body exactly as-is, to be used in a SOAP request.

// Copy the response body to a Chilkat BinData object.
bdSecToken := CkBinData_Create();
CkHttpResponse_GetBodyBd(resp,bdSecToken);

// Let's save the bdSecToken to a file, and pick it up in the next example where it is used
// in a SOAP request, such as in this example:  AddressBook Search for Professionals

CkBinData_WriteFile(bdSecToken,'qa_data/tokens/ehealth-fgov-be-sectoken.xml');

Memo1.Lines.Add('OK');

CkCert_Dispose(cert);
CkXml_Dispose(xmlToSign);
CkBinData_Dispose(bdCert);
CkDateTime_Dispose(dt);
CkXmlDSigGen_Dispose(gen);
CkXml_Dispose(xmlCustomKeyInfo);
CkStringBuilder_Dispose(sbXml);
CkHttp_Dispose(http);
CkHttpResponse_Dispose(resp);
CkBinData_Dispose(bdSecToken);

end;