https://digitaliseringskataloget.dk/integration/sf1601
If the MeMo version is not set explicitly on a message, this library set the version to MeMo 1.2.
The default version can be overridden by settings the SERVICEPLATFORMEN_MEMO_DEFAULT_VERSION environment variable to
one of the allowed values 1.1 or 1.2, e.g.
SERVICEPLATFORMEN_MEMO_DEFAULT_VERSION=1.1Calling this service is extremely simple, but it's extremely hard to navigate the documentation and understand how to actually authenticate and call the service.
As mentioned in SF1601 Programmer’s Guide, section 1.2 (Compatible frameworks) (cf. https://digitaliseringskataloget.dk/integration/sf1601), for calling the web service
The usage pattern is as follows:
(1) Request a SAML-token from the Security Token Service (REST) (2) Exchange the SAML-token to an Access Token (REST) (3) Invoke the service with the Access Token (REST)
All three step are simple basic HTTP-requests and thus compatible with all frameworks.
In the following section we will reveal what the first two simple HTTP-requests (sic!) actually are.
The Programmer’s Guide is easily accessible and can be opened using this simple command:
(cd /tmp; curl --location https://docs.kombit.dk/integration/sf1601/1.0/pakke --output SF1601.zip; unzip SF1601.zip 'SF1601 Bilag*.zip'; unzip "SF1601 Bilag*.zip"; open "SF1601 Bilag*/SF1601 Programmer's Guide.pdf")When downloading the documentation from https://digitaliseringskataloget.dk/integration/sf1601 you get a zip-file. This zip-file contains another zip file named "SF1601 Teknisk bilag.zip". This zip-file contains multiple json-files that can be viewed in a Swagger/OpenAPI viewer. One such viewer can be found here: https://editor.swagger.io/.
Assuming you have your certificate in the file certificate.p12 (or certificate.pfx) you first have to extract the
public certificate and the private key (cf. section 1.6 Certifikater in
https://digitaliseringskataloget.dk/files/integration-files/300620221422/Adgangsstyring%20for%20Brugere%20-%20Egen%20Identity%20Provider.pdf):
openssl pkcs12 -in certificate.p12 -out certificate.crt -nokeys -password pass:'«the p12 password»'
openssl pkcs12 -in certificate.p12 -out certificate.priv.key -nodes -nocerts -password pass:'«the p12 password»'Both the public certificate (certificate.crt) and the private key (certificate.priv.key) are in the PEM
format.
We also need the public certificate on a single line:
openssl x509 -in certificate.crt -trustout | sed '1,1d;$d' | tr -d '\n'Now we're ready to get to work.
A SAML token can be issued by POST'ing to
https://adgangsstyring.eksterntest-stoettesystemerne.dk/runtime/api/rest/wstrust/v1/issue (for test) or
https://adgangsstyring.stoettesystemerne.dk/runtime/api/rest/wstrust/v1/issue (for production) with the public
certificate and the private key. The request payload must be a JSON object containing your CVR number, your one-line
public certificate and an entity id depending on which service method you want to call (cf.
https://digitaliseringskataloget.dk/integration/sf1601):
{
"TokenType": "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",
"RequestType": "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue",
"KeyType": "http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey",
"AnvenderKontekst": {
"Cvr": «your CVR number»
},
"UseKey": «one-line public certificate»,
"AppliesTo": {
"EndpointReference": {
"Address": «the entity id»
}
},
"OnBehalfOf": null
}Apparently "UseKey" is not documented anywhere, but is required. The value must be the public certificate on a single
line (without -----(BEGIN|END) CERTIFICATE-----).
Using curl the SAML token request can be made like this:
# Export some variables for use in the JSON payload.
export CVR=«your CVR number»
# We want to call “KombiPostAfsend” (cf. https://digitaliseringskataloget.dk/integration/sf1601)
export ENTITY_ID=http://entityid.kombit.dk/service/kombipostafsend/1
export USE_KEY=$(openssl x509 -in certificate.crt -trustout | sed '1,1d;$d' | tr -d '\n')
curl --silent --cert certificate.crt --key certificate.priv.key https://adgangsstyring.eksterntest-stoettesystemerne.dk/runtime/api/rest/wstrust/v1/issue --request POST --header 'content-type: application/json' --data @- <<JSON
{
"TokenType": "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",
"RequestType": "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue",
"KeyType": "http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey",
"AnvenderKontekst": {
"Cvr": "$CVR"
},
"UseKey": "$USE_KEY",
"AppliesTo": {
"EndpointReference": {
"Address": "$ENTITY_ID"
}
},
"OnBehalfOf": null
}
JSONUsing jq you can put the SAML token into a
variable, SAML_TOKEN, for easy use in the next step:
export ENTITY_ID=http://entityid.kombit.dk/service/kombipostafsend/1
export CVR=«your CVR number»
export USEKEY=$(cat certificate.usekey)
export SAML_TOKEN=$(curl --silent --cert certificate.crt --key certificate.priv.key https://adgangsstyring.eksterntest-stoettesystemerne.dk/runtime/api/rest/wstrust/v1/issue --request POST --header 'content-type: application/json' --data @- <<JSON | jq --raw-output '.RequestedSecurityToken.Assertion'
{
"TokenType": "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",
"RequestType": "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue",
"KeyType": "http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey",
"AnvenderKontekst": {
"Cvr": "$CVR"
},
"UseKey": "$USEKEY",
"AppliesTo": {
"EndpointReference": {
"Address": "$ENTITY_ID"
}
},
"OnBehalfOf": null
}
JSON
)The SAML token can be exchanged for an access token by POST'ing it to
https://exttest.serviceplatformen.dk/service/AccessTokenService_1/token (test) or
https://prod.serviceplatformen.dk/service/AccessTokenService_1/token (production).
curl --silent --cert certificate.crt --key certificate.priv.key https://exttest.serviceplatformen.dk/service/AccessTokenService_1/token --data-urlencode "saml-token=$SAML_TOKEN"When succesful, the response will look like
{
"access_token": "1889e404-eada-4046-9283-73bda5a44e07",
"token_type": "Holder-of-key",
"expires_in": 3600
}And we're now ready for the final step.
Using the access token, we can now call the KombiPostAfsend
method using the token in the authorization header:
curl --silent --cert certificate.crt --key certificate.priv.key https://exttest.serviceplatformen.dk/service/KombiPostAfsend_1/kombi --header 'authorization: Holder-of-key 1889e404-eada-4046-9283-73bda5a44e07' --data @- <<'XML'
<kombi_request><KombiValgKode/></kombi_request>
XMLWe use xsd2php to generate PHP classes from XML Schema Definitions (XSD) from https://www.digitaliser.dk/resource/5248921 (MeMo_XSD.zip).
See bin/xsd2php for details on how XSDs are converted to PHP
classes.
To generate or update the generated PHP classes, run
docker run --rm --volume ${PWD}:/app itkdev/php8.3-fpm:latest composer install
docker run --interactive --tty --rm --volume ${PWD}:/app itkdev/php8.3-fpm:latest bin/xsd2phpA console command, bin/SF1601/kombipostafsend, can be used to send a test message using
the “KombiPostAfsend” service:
docker run --interactive --tty --rm --volume ${PWD}:/app itkdev/php8.3-fpm:latest bin/SF1601/kombipostafsend –-helpTo test with another default MeMo version, e.g. 1.1, run
docker run --env SERVICEPLATFORMEN_MEMO_DEFAULT_VERSION=1.1 --interactive --tty --rm --volume ${PWD}:/app itkdev/php8.3-fpm:latest bin/SF1601/kombipostafsend