I am trying to develop an integration scenario which requires a call to an external Electronic Identification service using SAML 2.0 protocol. I need to create an XML message in eIDAS format, which should be signed using SAML protocol, in order to make an authetication request.
This is a request message example provided by the WebService (which is called Cl@ve 2.0) .
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:eidas="http://eidas.europa.eu/saml-extensions" xmlns:eidas-natural="http://eidas.europa.eu/attributes/naturalperson" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" AssertionConsumerServiceURL="https://pre-pasarela.clave.gob.es/SP2/ReturnPage" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" Destination="https://se-pasarela.clave.gob.es/Proxy2/ServiceProvider" ForceAuthn="false" ID="_r1LZ7loli5ZpGJtb6avNQiVvGFX1qgenzkP6v--cWHCNZBIcjn8EtHe4l2xB1E_" IsPassive="false" IssueInstant="2018-07-30T07:32:22.571Z" ProviderName="S2833002E_E04975701;Demo-SP" Version="2.0">
<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/2001/04/xmldsig-more#rsa-sha512"/>
<ds:Reference URI="#_r1LZ7loli5ZpGJtb6avNQiVvGFX1qgenzkP6v--cWHCNZBIcjn8EtHe4l2xB1E_">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="eidas-natural"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
<ds:DigestValue>WowdQOy1xyCBZeNIe2CtqXXjr5rWyga2qzflk93EUpWmmCjeU83WpsIyPWy44CIXkdsOL+r3M3n4epCC5LMlOg==</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>H4LznEe1vzhRjw9MMvp4LlkTONWh2rhK1kli4+ivQOnX6TSFApXaekPAq6AleZjaP209HNQyaG4QOHe9aqfzC08rBaSIdbS/GGL/Z17mYz/oWOI7QafQVqCWHc4m08KeLf4bnWZKXXWlWcQNYw+k/rHleiO0Ulesi5Ro5BWKmMqehrjK/XRkyvH2aX6gylOZZAG27g627VpuxKw8NarM4FVb5dZ2OGKoFQojvBtUbZNecwM5+MRrMUBQKjOi05VPNCevIFB7JG17YnH5GPexGAhe1VDKV2tXWHcKPKnytgNk97d0JLDcJzEWZ0jjtTdRxcfqhkNsoJcVlUr7/jBWVw==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIF/TCCBOWgAwIBAgIQUj5ofy7TYXhWsKBZVz6lxDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
EwJFUzERMA8GA1UECgwIRk5NVC1SQ00xJTAjBgNVBAsMHEFDIENvbXBvbmVudGVzIEluZm9ybcOh
dGljb3MwHhcNMTYwMjAyMTIyNjAxWhcNMTkwMjAyMTIyNTU5WjCB2DELMAkGA1UEBhMCRVMxDzAN
BgNVBAcMBk1BRFJJRDE8MDoGA1UECgwzTUlOSVNURVJJTyBERSBIQUNJRU5EQSBZIEFETUlOSVNU
UkFDSU9ORVMgUMOaQkxJQ0FTMUswSQYDVQQLDEJESVJFQ0NJw5NOIERFIFRFQ05PTE9Hw41BUyBE
RSBMQSBJTkZPUk1BQ0nDk04gWSBMQVMgQ09NVU5JQ0FDSU9ORVMxEjAQBgNVBAUTCVMyODMzMDAy
RTEZMBcGA1UEAwwQRFRJQyBBR0UgUFJVRUJBUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALBcouy5wk1P1Lwq38b+mVbZfoqskPBepawieHarQ1NrkJJV+hIYOngGX/4DdpoUKr/ezAqr
Niu0mH1WxPI+eRLse1loUbjwQTgxnJI9QP0v79L6g0UqLyFcwyy7/dIxVkJUIq7qPHXbjvlgu5fC
w6uB8h0EQ2JlrpKfqtdkh+ipDmUfinageM11sMXEebS+YxO0iiqK0WgHPG27dSzd0Tfo2SKQ/XHs
guTtrIoV4kktGhkb7IEpO8+G8QzHd347HiQAy/MruzeLAJjaBhcYzkCmMFw5xWc7k6PB0S82heFB
6RN+4RGYP149VINGSQrS0WqIXrXJCHLQb5c7HBeNpm0CAwEAAaOCAlEwggJNMAkGA1UdEwQCMAAw
gYEGCCsGAQUFBwEBBHUwczA7BggrBgEFBQcwAYYvaHR0cDovL29jc3Bjb21wLmNlcnQuZm5tdC5l
cy9vY3NwL09jc3BSZXNwb25kZXIwNAYIKwYBBQUHMAKGKGh0dHA6Ly93d3cuY2VydC5mbm10LmVz
L2NlcnRzL0FDQ09NUC5jcnQwRAYDVR0gBD0wOzA5BgorBgEEAaxmAwkCMCswKQYIKwYBBQUHAgEW
HWh0dHA6Ly93d3cuY2VydC5mbm10LmVzL2RwY3MvMC4GA1UdEQQnMCWkIzAhMR8wHQYJKwYBBAGs
ZgEIDBBEVElDIEFHRSBQUlVFQkFTMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIE
sDAdBgNVHQ4EFgQUmUPaCKS1GXULRv7TYGFMG6BxmcQwHwYDVR0jBBgwFoAUGfhYLxTWpsybBJgI
DUzXqwCng2UwgeAGA1UdHwSB2DCB1TCB0qCBz6CBzIaBnmxkYXA6Ly9sZGFwY29tcC5jZXJ0LmZu
bXQuZXMvQ049Q1JMMSxPVT1BQyUyMENvbXBvbmVudGVzJTIwSW5mb3JtYXRpY29zLE89Rk5NVC1S
Q00sQz1FUz9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0O2JpbmFyeT9iYXNlP29iamVjdGNsYXNz
PWNSTERpc3RyaWJ1dGlvblBvaW50hilodHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9jcmxzY29tcC9D
UkwxLmNybDANBgkqhkiG9w0BAQsFAAOCAQEATlZ3DPFz1gQ32YOYIILzf99kuk2wFYULg+XaDqis
/y/S6bphKF3xbtyxsIX+lx0zI17dyDTKA+6sWNHiiuH4YjXkqbxbI8EYHfeRzbRK3S4Gj1yatGVt
hsCK6wDrlr8Rrj8QgntFAM+/kfysGJlHEiFsgTN2iXfOsjmXNNK1LwSbQ3GCwPaLYKZonNsEj8P/
S5r91ICejfGlVZp1AEXyP3jJzibr0SKxwEt32r/+ZjTmQgrLuAmGrgcVsjAAm2Cp7usJYaS/SyPF
j1QDUlZoVOuo4dfgFUZLCVBfMUBY73WNazVAojqZhG9d8tAgg2c64nusuMDY+25MLUKFzsbzFg==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Extensions>
<eidas:RequestedAttributes>
<eidas:RequestedAttribute FriendlyName="RelayState" Name="http://es.minhafp.clave/RelayState" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false">
<eidas:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eidas-natural:PersonIdentifierType">_v1m7pcn</eidas:AttributeValue>
</eidas:RequestedAttribute>
</eidas:RequestedAttributes>
</saml2p:Extensions>
<saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
<saml2p:RequestedAuthnContext Comparison="minimum">
<saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/low</saml2:AuthnContextClassRef>
</saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>I am unable to find ABAP libraries to make external request calls. I am also researching about SAP PI, but I cannot find any proper documentation about this kind of scenarios.
Request clarification before answering.
I was able to build the SAML2 XML. First of all, I defined a custom structure for the eIDAS attributes.
DATA(saml2_extensions) = VALUE xsdany( ).
DATA(eidas_attributes) = VALUE zsaml2p_eidas_attribute_t( (
friendlyname = `RelayState`
name = `http://es.minhafp.clave/RelayState`
nameformat = `urn:oasis:names:tc:SAML:2.0:attrname-format:uri`
isrequired = abap_false
value = VALUE #( ( get_secure_random( i_size = 8 ) ) ) ) ).
CALL TRANSFORMATION zsaml2_eidas_attribute SOURCE saml2_eidas_attributes = eidas_attributes RESULT XML saml2_extensions.I needed to create a simple SAP transformation to convert the ABAP structure to XML.
<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:eidas="http://eidas.europa.eu/saml-extensions"
xmlns:eidasnp="http://eidas.europa.eu/attributes/naturalperson"
xmlns:ddic="http://www.sap.com/abapxml/types/dictionary"
xmlns:def="http://www.sap.com/abapxml/types/defined">
<tt:root name="SAML2_EIDAS_ATTRIBUTES" type="ddic:ZSAML2P_EIDAS_ATTRIBUTE_T"/>
<tt:template>
<samlp:Extensions>
<eidas:RequestedAttributes>
<tt:loop ref=".SAML2_EIDAS_ATTRIBUTES">
<eidas:RequestedAttribute>
<tt:attribute name="Name" value-ref="NAME"/>
<tt:cond check="not-initial(NAMEFORMAT)">
<tt:attribute name="NameFormat" value-ref="NAMEFORMAT"/>
</tt:cond>
<tt:cond check="not-initial(FRIENDLYNAME)">
<tt:attribute name="FriendlyName" value-ref="FRIENDLYNAME"/>
</tt:cond>
<tt:cond check="not-initial(ISREQUIRED)">
<tt:attribute name="isRequired" value-ref="ISREQUIRED"/>
</tt:cond>
<tt:group>
<tt:cond frq="?">
<tt:loop ref="VALUE">
<eidas:AttributeValue>
<tt:value ref="$ref"/>
</eidas:AttributeValue>
</tt:loop>
</tt:cond>
</tt:group>
</eidas:RequestedAttribute>
</tt:loop>
</eidas:RequestedAttributes>
</samlp:Extensions>
</tt:template>
</tt:transform>In order to generate the SAML2 ticket, I used a standard ABAP structure.
DATA(issue_instant) = VALUE saml2_datetime( ).
GET TIME STAMP FIELD issue_instant.
DATA(saml_request) = VALUE saml2p_authn_request(
request = VALUE #(
id = get_secure_random( i_size = 64 )
version = if_saml20_constants=>co_saml_version
issueinstant = issue_instant
destination = `https://se-pasarela.clave.gob.es/Proxy2/ServiceProvider`
consent = `urn:oasis:names:tc:SAML:2.0:consent:unspecified`
extensions = saml2_extensions )
nameid = VALUE #( allowcreate = abap_true idformat = wssec_co_saml_nid_form_unspec )
authncontext = VALUE #( comparison = if_saml20_constants=>co_comparison_method_s_minimum authncontextclassref = VALUE #( ( `http://eidas.europa.eu/LoA/low` ) ) )
forceauthn = abap_true
ispassive = abap_false
providername = `S2833002E_E04975701;Demo-SP`
assertionconsumerserviceurl = `https://pre-pasarela.clave.gob.es/SP2/ReturnPage` ).The next step is the signature, using standard classes. The important part here is to set the SAML2 Request Schema in the signature transformation.
TRY.
DATA(xml_signer) = cl_sec_sxml_dsignature=>create_writer_instance( ).
" Digestion over ID attritube of samlp:AuthnRequest node
xml_signer->set_attributes(
if_str_transform = abap_false " Disable standard transformation
if_attribute_name = 'ID'
if_attribute_namespace = if_saml20_constants=>co_saml_protocol_support ).
" ENV-C14N-EXC signature with RSA-SHA512 algorithm
xml_signer->m_pse_context = cl_sec_sxml_dsignature=>co_ssfa.
xml_signer->m_signature_type = cl_sec_sxml_dsignature=>co_type_enveloped.
xml_signer->m_signature_transformation = cl_sec_sxml_dsignature=>co_transform_envelope.
xml_signer->m_canonicalization = cl_sec_sxml_dsignature=>co_c14n_exclusive.
xml_signer->m_signature_ns_prefix = cl_sec_sxml_dsignature=>co_signature_nsprefix.
xml_signer->m_signature_id = space.
xml_signer->m_dsig_hash_algorithm = 'SHA512'.
xml_signer->m_ssf_hash_algorithm = 'SHA512'.
xml_signer->m_dsig_method = cl_sec_sxml_dsignature=>co_dsig_method_rsa.
" Use SAML2 schema for the XSLT transformation
xml_signer->set_transformation(
EXPORTING
if_name = 'SAML2_AUTHN_REQUEST'
if_data_tab = VALUE #( ( name = 'SAML2_AUTHN_REQUEST' value = saml_request ) )
CHANGING
ch_signature_data = saml_request->request-signature_raw ).
" Sign using PSE certificate stored in STRUST
xml_signer->sign_xml(
if_ssf_app = if_saml20_constants=>co_ssfappl_sp_sign " S2SVPS
if_add_keyinfo = abap_true
if_re_transform = abap_true ).
CATCH cx_sec_sxml_error.
RAISE EXCEPTION TYPE cx_saml20_core EXPORTING textid = cx_saml20_core=>xml_create_error.
ENDTRY.I used an already existing STRUST app to store the certificate for the signature. However, you can use a custom one if you want.
Once the XML is signed, you can generate the final XML using a standard transformation.
CALL TRANSFORMATION saml2_authn_request SOURCE saml2_authn_request = saml_request RESULT XML DATA(signed_xml) OPTIONS xml_header = 'no'.With this approach, I was able to generate the SAML2 ticket with the required format.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 5 | |
| 4 | |
| 4 | |
| 3 | |
| 2 | |
| 2 | |
| 2 | |
| 2 | |
| 2 | |
| 2 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.