Sample code for 30+ languages & platforms
PureBasic

eHealth.gov.be RequestSecurityToken

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

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkBinData.pb"
IncludeFile "CkDateTime.pb"
IncludeFile "CkHttp.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkXmlDSigGen.pb"
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkHttpResponse.pb"
IncludeFile "CkCert.pb"

Procedure ChilkatExample()

    success.i = 0

    ; 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.i = CkCert::ckCreate()
    If cert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkCert::ckLoadPfxFile(cert,"SSIN=12345678.acc.p12","p12_password")
    If success = 0
        Debug CkCert::ckLastErrorText(cert)
        CkCert::ckDispose(cert)
        ProcedureReturn
    EndIf

    ; 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.i = CkXml::ckCreate()
    If xmlToSign.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::setCkTag(xmlToSign, "soapenv:Envelope")
    CkXml::ckAddAttribute(xmlToSign,"xmlns:ns","http://docs.oasis-open.org/ws-sx/ws-trust/200512")
    CkXml::ckAddAttribute(xmlToSign,"xmlns:soapenv","http://schemas.xmlsoap.org/soap/envelope/")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security",1,"xmlns:wsse","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security",1,"xmlns:wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",1,"EncodingType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",1,"ValueType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",1,"wsu:Id","X509-4A13D668E59AAC4F3816750824965588")

    bdCert.i = CkBinData::ckCreate()
    If bdCert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkCert::ckExportCertDerBd(cert,bdCert)
    CkXml::ckUpdateChildContent(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",CkBinData::ckGetEncoded(bdCert,"base64"))

    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsu:Timestamp",1,"wsu:Id","TS-4A13D668E59AAC4F3816750824965567")

    dt.i = CkDateTime::ckCreate()
    If dt.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkDateTime::ckSetFromCurrentSystemTime(dt)
    CkXml::ckUpdateChildContent(xmlToSign,"soapenv:Header|wsse:Security|wsu:Timestamp|wsu:Created",CkDateTime::ckGetAsTimestamp(dt,0))
    CkDateTime::ckAddSeconds(dt,300)
    CkXml::ckUpdateChildContent(xmlToSign,"soapenv:Header|wsse:Security|wsu:Timestamp|wsu:Expires",CkDateTime::ckGetAsTimestamp(dt,0))
    CkDateTime::ckAddSeconds(dt,-300)

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

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

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

    gen.i = CkXmlDSigGen::ckCreate()
    If gen.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXmlDSigGen::setCkSigLocation(gen, "soapenv:Envelope|soapenv:Header|wsse:Security|wsse:BinarySecurityToken")
    CkXmlDSigGen::setCkSigLocationMod(gen, 1)
    CkXmlDSigGen::setCkSigId(gen, "SIG-4A13D668E59AAC4F38167508249656212")
    CkXmlDSigGen::setCkSigNamespacePrefix(gen, "ds")
    CkXmlDSigGen::setCkSigNamespaceUri(gen, "http://www.w3.org/2000/09/xmldsig#")
    CkXmlDSigGen::setCkSignedInfoPrefixList(gen, "soapenv urn urn1")
    CkXmlDSigGen::setCkIncNamespacePrefix(gen, "ec")
    CkXmlDSigGen::setCkIncNamespaceUri(gen, "http://www.w3.org/2001/10/xml-exc-c14n#")
    CkXmlDSigGen::setCkSignedInfoCanonAlg(gen, "EXCL_C14N")
    CkXmlDSigGen::setCkSignedInfoDigestMethod(gen, "sha256")

    ; Set the KeyInfoId before adding references..
    CkXmlDSigGen::setCkKeyInfoId(gen, "KI-4A13D668E59AAC4F3816750824965589")

    ; -------- Reference 1 --------
    CkXmlDSigGen::ckAddSameDocRef(gen,"TS-4A13D668E59AAC4F3816750824965567","sha256","EXCL_C14N","wsse soapenv urn urn1","")

    ; -------- Reference 2 --------
    CkXmlDSigGen::ckAddSameDocRef(gen,"id-4A13D668E59AAC4F38167508249655911","sha256","EXCL_C14N","urn urn1","")

    ; -------- Reference 3 --------
    CkXmlDSigGen::ckAddSameDocRef(gen,"X509-4A13D668E59AAC4F3816750824965588","sha256","EXCL_C14N","_EMPTY_","")

    CkXmlDSigGen::ckSetX509Cert(gen,cert,1)

    CkXmlDSigGen::setCkKeyInfoType(gen, "Custom")

    ; Create the custom KeyInfo XML..
    xmlCustomKeyInfo.i = CkXml::ckCreate()
    If xmlCustomKeyInfo.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::setCkTag(xmlCustomKeyInfo, "wsse:SecurityTokenReference")
    CkXml::ckAddAttribute(xmlCustomKeyInfo,"wsu:Id","STR-4A13D668E59AAC4F38167508249655810")
    CkXml::ckUpdateAttrAt(xmlCustomKeyInfo,"wsse:Reference",1,"URI","#X509-4A13D668E59AAC4F3816750824965588")
    CkXml::ckUpdateAttrAt(xmlCustomKeyInfo,"wsse:Reference",1,"ValueType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3")

    CkXml::setCkEmitXmlDecl(xmlCustomKeyInfo, 0)
    CkXmlDSigGen::setCkCustomKeyInfoXml(gen, CkXml::ckGetXml(xmlCustomKeyInfo))

    ; Load XML to be signed...
    sbXml.i = CkStringBuilder::ckCreate()
    If sbXml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::ckGetXmlSb(xmlToSign,sbXml)

    CkXmlDSigGen::setCkBehaviors(gen, "IndentedSignature")

    ; Sign the XML...
    success = CkXmlDSigGen::ckCreateXmlDSigSb(gen,sbXml)
    If success = 0
        Debug CkXmlDSigGen::ckLastErrorText(gen)
        CkCert::ckDispose(cert)
        CkXml::ckDispose(xmlToSign)
        CkBinData::ckDispose(bdCert)
        CkDateTime::ckDispose(dt)
        CkXmlDSigGen::ckDispose(gen)
        CkXml::ckDispose(xmlCustomKeyInfo)
        CkStringBuilder::ckDispose(sbXml)
        ProcedureReturn
    EndIf

    ; The sbXml is sent as the HTTP request body below..
    Debug CkStringBuilder::ckGetAsString(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.i = CkHttp::ckCreate()
    If http.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkHttp::ckSetSslClientCert(http,cert)
    If success = 0
        Debug CkHttp::ckLastErrorText(http)
        CkCert::ckDispose(cert)
        CkXml::ckDispose(xmlToSign)
        CkBinData::ckDispose(bdCert)
        CkDateTime::ckDispose(dt)
        CkXmlDSigGen::ckDispose(gen)
        CkXml::ckDispose(xmlCustomKeyInfo)
        CkStringBuilder::ckDispose(sbXml)
        CkHttp::ckDispose(http)
        ProcedureReturn
    EndIf

    CkHttp::ckSetRequestHeader(http,"Content-Type","text/xml")

    url.s = "https://services-acpt.ehealth.fgov.be/IAM/SecurityTokenService/v1/RequestSecurityToken"
    resp.i = CkHttpResponse::ckCreate()
    If resp.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkHttp::ckHttpSb(http,"POST",url,sbXml,"utf-8","application/xml",resp)
    If success = 0
        Debug CkHttp::ckLastErrorText(http)
        CkCert::ckDispose(cert)
        CkXml::ckDispose(xmlToSign)
        CkBinData::ckDispose(bdCert)
        CkDateTime::ckDispose(dt)
        CkXmlDSigGen::ckDispose(gen)
        CkXml::ckDispose(xmlCustomKeyInfo)
        CkStringBuilder::ckDispose(sbXml)
        CkHttp::ckDispose(http)
        CkHttpResponse::ckDispose(resp)
        ProcedureReturn
    EndIf

    responseStatus.i = CkHttpResponse::ckStatusCode(resp)
    Debug "Response Status Code = " + Str(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.

    Debug CkHttpResponse::ckBodyStr(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.i = CkBinData::ckCreate()
    If bdSecToken.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkHttpResponse::ckGetBodyBd(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::ckWriteFile(bdSecToken,"qa_data/tokens/ehealth-fgov-be-sectoken.xml")

    Debug "OK"


    CkCert::ckDispose(cert)
    CkXml::ckDispose(xmlToSign)
    CkBinData::ckDispose(bdCert)
    CkDateTime::ckDispose(dt)
    CkXmlDSigGen::ckDispose(gen)
    CkXml::ckDispose(xmlCustomKeyInfo)
    CkStringBuilder::ckDispose(sbXml)
    CkHttp::ckDispose(http)
    CkHttpResponse::ckDispose(resp)
    CkBinData::ckDispose(bdSecToken)


    ProcedureReturn
EndProcedure