SAML Integration Guide

1. What Is SAML 2.0

SAML is a standard that addresses web-browser single sign-on (SSO). SAML 2.0 is an XML-based protocol that uses security tokens containing assertions to pass information about a principal (usually an end-user) between an Identity Provider and a Service Provider.

The SAML flow is shown in the diagram below:

  1. The user via the UserAgent (e.g Browser) tries to access the SP

  2. The SP checks the current authentication session of the user and:

    1. If the user still has a valid session provides the user access to the service.

    2. If the user does not have a valid session, it will generate a AuthNRequest and redirects the user to the IDP’s SingleSignOnService URL

  3. The IDP checks the AuthNRequest and if valid ask the UserAgent to provide authentication details.

  4. The UserAgent provided the authentication details to the IDP.

  5. The IDP checks the user credentials and if valid generates a SAMLResponse containing a SAML Assertion about the user attributes.

  6. The IDP sends the SAMLResponse (through the UserAgent) to the AssertionConsumerService url of the SP.

  7. The SP validates the SAML Response and assertions and if valid provides the user access to the service.

2. Integration

2.1. Setup

For SAML Integration the Service Provider and the Identity Provider first need to exchange their endpoints and signing-certificates with each other. Usually, this is done by exchanging a SAML Metadata document. The metadata of Audkenni can be downloaded here. An example of the metadata document that a service needs to provide can be downloaded here:

2.2. Request

In some cases, the Service Provider is also an IDP that received a request from other SPs (Relaying parties) and relies on Audkenni for the actual authentication. This scenario is seen in the picture below.

 

In this scenario, Audkenni mandates that this information, name of the RelatedPartyParty, is provided in the AuthnRequest as an extension attribute named audkenni:relatedPartyParty, e.g.:

1 <audkenni:relatedPartyParty xmlns:audkenni="urn:audkenni">Example client</audkenni:relatedPartyParty>

An example full AuthnRequest would then look as follows:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="UTF-8"?> <saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://localhost:8080/saml/SSO" Destination="https://idp-dev.audkenni.is/sso/SSORedirect/metaAlias/audkenni/idp" ForceAuthn="false" ID="a57h5jf2jdffa5553d58332jc831g7b" IsPassive="false" IssueInstant="2019-11-28T13:27:04.831Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">com:audkenni:spring:sp</saml2:Issuer> <md:Extensions xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> <audkenni:relatedPartyParty xmlns:audkenni="urn:audkenni">Example client</audkenni:relatedPartyParty> </md:Extensions> </saml2p:AuthnRequest>

2.2.2. Providing the login message

The message that the user receives during authentication (e.g. on his phone/app/nexus card) can also be provided in the AuthNRequest as an extension attribute named audkenni:signingMessage, e.g.:

1 <audkenni:signingMessage xmlns:audkenni="urn:audkenni">Login to example client</audkenni:signingMessage>

An example full AuthnRequest would then look as follows:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?xml version="1.0" encoding="UTF-8"?> <saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://localhost:8080/saml/SSO" Destination="https://idp-dev.audkenni.is/sso/SSORedirect/metaAlias/audkenni/idp" ForceAuthn="false" ID="a57h5jf2jdffa5553d58332jc831g7b" IsPassive="false" IssueInstant="2019-11-28T13:27:04.831Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">com:audkenni:spring:sp</saml2:Issuer> <md:Extensions xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> <audkenni:relatedPartyParty xmlns:audkenni="urn:audkenni">Example client</audkenni:relatedPartyParty> <audkenni:signingMessage xmlns:audkenni="urn:audkenni">Login to example client</audkenni:signingMessage> </md:Extensions> </saml2p:AuthnRequest>

If no signingMessage is provided, the user will receive the message “Login to Audkenni”.

2.2.3. Influencing the login flow

The login flow the user experiences can be influenced by setting a “RequestedAuthnContext“ in the AuthnRequest. At the moment the following contexts are supported

  • urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport

    • In this case, the default login flow would be presented in which the user can choose the authentication method

  • urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI

    • In this case, only the nexus personal card authentication option is shown

  • urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract

    • In this case, only the Sim card authentication option is shown

 

An example AuthNRequest where for instance the sim card option is enforced looks like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" encoding="UTF-8"?> <saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://localhost:8080/saml/SSO" Destination="https://idp-dev.audkenni.is/sso/SSORedirect/metaAlias/audkenni/idp" ForceAuthn="false" ID="a57h5jf2jdffa5553d58332jc831g7b" IsPassive="false" IssueInstant="2019-11-28T13:27:04.831Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">com:audkenni:spring:sp</saml2:Issuer> <md:Extensions xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> <audkenni:relatedPartyParty xmlns:audkenni="urn:audkenni">Example client</audkenni:relatedPartyParty> <audkenni:signingMessage xmlns:audkenni="urn:audkenni">Login to example client</audkenni:signingMessage> </md:Extensions> <saml2p:RequestedAuthnContext Comparison="exact"> <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract</saml:AuthnContextClassRef> </saml2p:RequestedAuthnContext> </saml2p:AuthnRequest>

2.3. Response

NameID

The social security number of the user is set as the NameID in the authentication response

attributes

In the SAML Assertion, the following attributes are returned

  • nationalRegisterId

    • The social security number

  • certificate

    • The certificate generated by the authenticator as a result of the user authentication

As a reference, a complete SAML Response looks as follows:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s2cfc8184b0da6eda25d8387069c56e04c371a58f5" InResponseTo="a36gea5c57j4d4a44g48ce7935bdcfd" Version="2.0" IssueInstant="2019-11-28T14:11:39Z" Destination="http://localhost:8080/saml/SSO"> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp-audkenni</saml:Issuer> <samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Value="urn:oasis:names:tc:SAML:2.0:status:Success"> </samlp:StatusCode> </samlp:Status> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="s23714053df35586d1af847599c20670e2763ef42a" IssueInstant="2019-11-28T14:11:39Z" Version="2.0"> <saml:Issuer>idp-audkenni</saml:Issuer> <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-sha256" /> <ds:Reference URI="#s23714053df35586d1af847599c20670e2763ef42a"> <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#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> <ds:DigestValue>SqUIJ1nnASEhTYa2xVWtnuP36wTgABsLaljgE/qKqr0=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> ZbVFAqIoNrxgyxFjZPP5lWsPhbosUuGlNV/dDVWpxDEDJFuVwDBdcmQTWzlu8ZyOIwL+xAXIm+Pg&#13; 5QnURv7IkLGvkcgpWF7roAm5pw2Wi7Q9xoIVpQcUqdLn4Ja8P/FM9m0TuzkdwzPmxLKzBn1sq1Op&#13; UegBFYETlb8q+JhsC4Qd/wvYgriGiMIE95y7jWGHYbf+AhptXqpLhPYFjGtc8KxDbIe1pFpA61+J&#13; S8yDANcHV5GqklvhZNAS/Ytjtr+gejo1rxjaiQP9r3AIoQZmNrZPvlj/R58cEgc+SlrETao9kAA4&#13; 6uoQA0mY36QVArBsjnrk2ljn400lJM4Ylr37HPbbXug8W2xFvq8XmlxgpREaQSmKp2MZCzMv3few&#13; /vgHCOUzctz4UYhxYGsjJnGS9R61ipCHDiXtb4xSOuYPNG+bOO8rdS41YssdnHIHBmrP7jp+2vMu&#13; 7R6sGNeksJD2WHF+JZUDgqkiTyp4HgpXiBEggGN7Xz5vSKMSos2ERW32 </ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> MIID/zCCAmegAwIBAgIEfaPy4jANBgkqhkiG9w0BAQsFADAwMQswCQYDVQQGEwJJUzERMA8GA1UE&#13; ChMIQXVka2VubmkxDjAMBgNVBAMTBXNhbWwyMB4XDTE5MTExNTA5MTUxNFoXDTI5MTEyMjA5MTUx&#13; NFowMDELMAkGA1UEBhMCSVMxETAPBgNVBAoTCEF1ZGtlbm5pMQ4wDAYDVQQDEwVzYW1sMjCCAaIw&#13; DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKe912NIWn2B+axdhdESiFMnIK23dJ8TCV/Tcl9X&#13; iT1Sgc8WTSNU9a2RZoEaC7pR+3q7CQXJZ3LenCO77PwwB1PFioXRM7DY7v2C6XorBT1TmQYTyNDn&#13; zsgHCoxLAPBEkpFN9MRtiaQedzTC7ZaR36RhsGNdQVVPXSMgbSCNamesDWgqC4D1CiV/d02DFLXS&#13; Kr3D4/Q5ZU/IA8+tMvEv6nwvhgYBcBElmtaZZSA7QZbR2ogziMUZq4VlxXcu9n+wBkvQ6RYBRf4e&#13; 5SumJOPAG2KOH7sCAqfu28kxisrtuP4DUvx1cY7u2GYmrY11sf96DwLoAn/9IAADC1nY8ehKi1k1&#13; y84xwq/ovyfYozW3wkpHb5TQhiAq5rFbiUfFGmfqMH0kIL7WRAG7eVJ45S9nXYdpYvvdkR94oSfL&#13; uS9VOoBggCHXokNKfntbx0oX2QSGzSpmRTrJ2efDIVUDeiIyaIOkoc9c/AanNfkdbkF0z9vx3SB3&#13; sM3ec/y/Tl5u6fz+FwIDAQABoyEwHzAdBgNVHQ4EFgQUpw9ZOOWOtzE8CgGZhiWSJVLKonIwDQYJ&#13; KoZIhvcNAQELBQADggGBAAAMv6DGLxe6exRRzJ6ygBzSpiUgoRBAWPBERB9JEHeuV193UCoLkz12&#13; PJ3wYQQPUr4Fwz/2BnXXo0Hx0cZ5MFF4+oQSvuLCIqAJBaXUnlYPVvnQ0z6df5QNnb59wUsci+gV&#13; 1Es9kyPPS2CeDynvLEdFjjKeVuoDI6rvNgxkA6+6oUwhQLhB0qMjjciuMs5S0pJuif0hJ3EwGf7V&#13; 0XU4DAtk5xlhFyJj7CpYmgjbR/2FEYpqiK4W99VJo+BQu8/X1GsOHm1JzJ3Y3QrrUWWaE1FITxyr&#13; 3sZs+psmzW/yj3gDuzvOcOLW5CjwXa9o5W6gSE8jI/aD0H+0yUjYIEFJzLxa9qBYjGolpB4vOTFy&#13; YEyrsTlWtaSZXSALefFDwIDeLpblunwKK0FrsQkLMPGrOejGwOcO7MR1VgjObqZ9EYtuaJ6tFDzK&#13; vs6HXpV73NpvxT6iGd1R7/r+T25mo1yMr90GuJrH5QrSpz6gFB7BN3YZH41HUwKsw/0pdTB4UdZf&#13; fQ== </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="idp-audkenni">10101303369</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="a36gea5c57j4d4a44g48ce7935bdcfd" NotOnOrAfter="2019-11-28T14:21:39Z" Recipient="http://localhost:8080/saml/SSO" /></saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2019-11-28T14:01:39Z" NotOnOrAfter="2019-11-28T14:21:39Z"> <saml:AudienceRestriction> <saml:Audience>com:audkenni:spring:sp</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2019-11-28T14:11:38Z" SessionIndex="s24e3d69c700574c47516412d3a2a92b3a3529c601"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="certificate"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"> 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 </saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="nationalRegisterId"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">0101303369</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response>