SAML 2.0 Single sign-on protocol implementation

Protocol overview

Security Assertion Markup Language (SAML, pronounced sam-el) is an open standard for exchanging authentication and authorization data between parties, in particular, between an identity provider and a service provider. As its name implies, SAML is an XML-based markup language for security assertions (statements that service providers use to make access-control decisions).

The single most important use case that SAML addresses is web browser single sign-on (SSO). Single sign-on is relatively easy to accomplish within a security domain (using cookies, for example) but extending SSO across security domains is more difficult and resulted in the proliferation of non-interoperable proprietary technologies. The SAML Web Browser SSO profile was specified and standardized to promote interoperability.

For more information concerning the protocol itself, please refer to the following Wikipedia article.

To use SAML for SSO into Corteos you have to do the following steps:

  1. Obtain a certificate for assertion signature;
  2. Configure SSO Portal endpoint to understand this certificate(see below);
  3. Add all mandatory static claims to request
  4. Prepare the HTTP POST request
  5. Send data to SSO Portal

Please, note that we do not consult on SAML protocol itself(e.g. how to create or validate request and so on), please find any SAML implementation available at your platform. Some good places to start with:

Configuring endpoint

First of all we need to set up our endpoint, otherwise Corteos won't understand your request. You need to have your certificate in .cer format to obtain to get the following data from it's properties:

You have to double click on certificate file to open this window, after it copy the serial number and remove whitespaces. After it you can open the following link to configure the endpoint.

Use your travel manager account(email and password) and group identifier to login into settings manager page.

Set the following settings on this administrative page:

  • Type = SAML
  • User redirect link - absolute url(with protocol) where the user will be redirected after successfull single sign on
  • Serial number - our certificate serial number(the one we've obtained from .cer file)

After you are done with it press the save button to save our SSO settings and consider server endpoint configuration is finished.

Mandatory and optional claims

Below you can see SAML request created by okta service:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://newbooking.continent.ru/ExternalAuth/SAMLAuth" ID="id36172247630962764663388050" IssueInstant="2017-10-05T09:43:36.713Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/xxxxxxxxxxxxx</saml2: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="#id36172247630962764663388050">
				<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="xs"/>
					</ds:Transform>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>y5XHhFgPkn3+p7a62C7yxCiLR3HTsVPkS047wF8BXh4=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>hQIlv8Qjl8bEGIad7RjS3izPveLJMMO0N9bslAa/ENx7HgjmxGWN8l4RLmVgc2l9wsIzH+yO06COyjw0HwU1MZcsbGwJtNYHg4nsP4lvu8yhWbhHiL42PcJNidnb2nvJEzV/d0VP6UM4e7QfR5X0fVsy3aPjApvz+zmZPLEAMMQjwRLmmkz+eC39dsceYDkW7woPylFEt+iDIgN20buv3h2eQKn6h4+rmxIjrucP4iA+IT3lubOqUwCmDkyXyj/ozrG3iRU3jC+dveDgHWEDsGlKJ46JG4w9v5ruTS9T6Q9F0zFxL1hDLoEAMP37D3hVnwgxZMSDo47zyYxRsN8/2Q==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
		<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
	</saml2p:Status>
	<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="id361722476309898741423156490" IssueInstant="2017-10-05T09:43:36.713Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
		<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.okta.com/xxxxxxxxxxxxx</saml2: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="#id361722476309898741423156490">
					<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="xs"/>
						</ds:Transform>
					</ds:Transforms>
					<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
					<ds:DigestValue>9Fay8bYtofYv9iGwkaIY21SvGML1NWdzRBei+k3nZ88=</ds:DigestValue>
				</ds:Reference>
			</ds:SignedInfo>
			<ds:SignatureValue>G9IYQlckhcFbsD3ToyFaRjlJGXnd9NN1uK6TIcfUlqTwPPARhTdcCVXPawluvpvjO2aXAGu5SlDy4g+j5gEMGMxMD27l4XhQvzya+sKjmt5jPI03VF6g815lr7ZcJ3djMzkAROMuYd59FpTfn8eN9EuJx9Cci0MYTz2C8qTO6tYG8jtWvAxfwQjUY1kRHkWCpt5gJgFVMYgwblvJBciKoK3FohvgLNVIdR0p/QTZv2EnGIsuZieygi+cENzDZ6JvKeH3AyZ/Won2IuUGRFBUUj1yWOrWPPj2gktGtUuHO70q+/y+A/JvfZsrJSr0lVMi68sdG+AENQpNMYiZahJvzQ==</ds:SignatureValue>
			<ds:KeyInfo>
				<ds:X509Data>
					<ds:X509Certificate>xxxxxxxxxxxxxxxxxx</ds:X509Certificate>
				</ds:X509Data>
			</ds:KeyInfo>
		</ds:Signature>
		<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">test@test.com</saml2:NameID>
			<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml2:SubjectConfirmationData NotOnOrAfter="2017-10-05T09:48:36.713Z" Recipient="https://domain.com"/>
			</saml2:SubjectConfirmation>
		</saml2:Subject>
		<saml2:Conditions NotBefore="2017-10-05T09:38:36.713Z" NotOnOrAfter="2017-10-05T09:48:36.713Z" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:AudienceRestriction>
				<saml2:Audience>https://domain.com</saml2:Audience>
			</saml2:AudienceRestriction>
		</saml2:Conditions>
		<saml2:AuthnStatement AuthnInstant="2017-10-05T09:43:36.713Z" SessionIndex="id1507196616713.950228573" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:AuthnContext>
				<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
			</saml2:AuthnContext>
		</saml2:AuthnStatement>
		<saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:Attribute Name="pass id_Group" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">123</saml2:AttributeValue>
			</saml2:Attribute>
			<saml2:Attribute Name="RequestId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">xxxxx-xxxxx-xxxxx-xxxxx</saml2:AttributeValue>
			</saml2:Attribute>
			<saml2:Attribute Name="SignOutUrl" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">https://mybackurl.com</saml2:AttributeValue>
			</saml2:Attribute>
		</saml2:AttributeStatement>
	</saml2:Assertion>
</saml2p:Response>

Please notice some additional claims added into AttributeStatement section: some of them are mandatory and some are optional, but still may be required due to your business process specifics

  • pass id_Group - mandatory - int, unique group identifier, a constant
  • SignOutUrl - optional - string, if you need to drop user to a specific url after he does sign out, pass this url as a parameter
  • RequestId - optional - string(guid), unique request identifier, pass it in case you use this web service along with SSO.

Sending data to endpoint

SAML Response is transfered to the endpoint via HTTP POST, before you do it, please do the following operations with your XML:

  • base64 encode plain request
  • optionally url encode(it's recommended to try send just base64 encoded request at first during development - various client platforms may either require or not to do this encoding)

After the packing is done make the following POST:

curl -d "SAMLResponse=PD94***SKIPPED***bWwycDpSZXNwb25zZT4=" -X POST http://sso-portal-domain.com/SamlAuth
SAML Test form