-
Notifications
You must be signed in to change notification settings - Fork 13
SAML2 and SSO
Authentication is the verification that a username and password is correct and corresponds to an existing user.
Authorization is making sure that the user that sends requests to the server is the same user that has been authenticated and that they have the roles needed to access the resources they are attempting to.
SAML2 stands for Security Assertion Markup Language and you can fundamentally think of it as an XML payload sent over HTTP that proves an actor is who they say they are. The user identity data within these assertions are in the form of XML attributes such as email, username, etc and are referred to as claims.
Example SAML request response pair:
Request:
Response:
IdP: Identity Providers. These are the services that manage and store user credentials, such as Amazon Cognito for those of us who have taken or are taking CCP or Azure Active Directory for the Telescope project.
SP: This stands for service provider and is what the actor would like access to, any application or website that you need authentication to access full functionality, to connect to, etc.
SSO: Single Sign On, meaning a user can sign in with one set of credentials across several websites/services.
STS: Security Token Service. (TODO)
Claims: In the case of the SAML protocol these are XML attributes such as email, username, etc that come from an IdP that claim the user is such and such.
As an example in the Telescope project the claims posted had profile information in this JSON format. This came back from the Azure Active Directory to the callback Url defined in the passport configuration once a user signed into their Microsoft account.
{
"issuer": "https://sts.windows.net/...idp-uuid.../",
"inResponseTo": "_851...",
"sessionIndex": "_dfa...",
"nameID": "username@seneca-domain.ca",
"nameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
"http://schemas.microsoft.com/identity/claims/tenantid": "...app-uuid...",
"http://schemas.microsoft.com/identity/claims/objectidentifier": "...uuid...",
"http://schemas.microsoft.com/identity/claims/displayname": "Full Name",
"http://schemas.microsoft.com/identity/claims/identityprovider": "https://sts.windows.net/...app-uuid.../",
"http://schemas.microsoft.com/claims/authnmethodsreferences": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": "Firstname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname": "Lastname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "username@seneca-domain.ca",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "username@seneca-domain.ca",
"sAMAccountName": "username"
}
Bindings: There are several methods of transporting requests and responses in the SAML auth flow, these are called bindings. Two popular examples are those of HTTP Redirect Binding which is when SAML protocol messages are transmitted through URL paramaters, and HTTP Post Binding which is when SAML protocol messages are transmitted through HTML forms that are base 64 encoded (Source). For simplicity, consider a system that uses redirect for SAML requests and Post for SAML response. Conceptualize redirect bindings as the little login forms that pop up when you press login with the huge URIs and post bindings as an automated post to a predetermined endpoint on our server that's hit after authentication.
The above is an example using telescope and Azure AD of a redirect binding that is used for a SAMLRequest, for logging us into the IdP (the previously mentioned Azure AD).
This is the route that is configured as a POST binding for after you are logged in although it returned a 400 for me for some reason.
In any case when it works it posts data back to a preconfigured endpoint on Telescope. It sends back the SAML Response in base64 encoded form in the payload, once decrypted it's a readable XML assertion like so:
<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_dc4db0e2-57bb-4b01-b8fd-1b7b444ecc3f" Version="2.0" IssueInstant="2023-01-16T14:32:30.180Z" Destination="https://api.telescope.cdot.systems/v1/auth/login/callback" InResponseTo="_808ba4a2112df99f1409">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/eb34f74a-58e7-4a8b-9e59-433e4c412757/</Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_5ffeffda-dbc1-4a3a-8e38-737a77271400" IssueInstant="2023-01-16T14:32:30.180Z" Version="2.0">
<Issuer>https://sts.windows.net/eb34f74a-58e7-4a8b-9e59-433e4c412757/</Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#_5ffeffda-dbc1-4a3a-8e38-737a77271400">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>9aa9rOxkCQPw/C+I4S3tURCHeomfZ2BNzNuw64rNrXI=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>j1VrPNq4CDDzeh3k36P7u5LbXD1RCk90Zr1y+csanBCLBIp15zvfOObj+I4/rnRkECbKlCsy9nBuqPEq2DK7/cKs7zWe9Uk4A+3Ef5cZ2JotNlrtL+mqpKG32MBgEzCkGxHV2x5cDYKNBInZibsd5kb5p8F24nTUZxRUuVD7GGWIGPiv5x1/Rk+LsIF0caFuhB64uu5PzHJiyIpODRGCPX7ulx3sJSrkZ/TT3n3v0JG0ncJFPR9paqUOJvvvsFBO5z+SSSB7rDSxFUZquL1mz4xTtBaQD5rUXeHpHlitRMDUjW3BrP8uUloMgHtZdQJbpMdgig91anPbFHOVoPc3jQ==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC8DCCAdigAwIBAgIQdkwaL5ZETpxKCS6P5jD5QzANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQDEylNaWNyb3NvZnQgQXp1cmUgRmVkZXJhdGVkIFNTTyBDZXJ0aWZpY2F0ZTAeFw0yMDA0MTMxNTA1NDNaFw0yMzA0MTMxNTA1NDNaMDQxMjAwBgNVBAMTKU1pY3Jvc29mdCBBenVyZSBGZWRlcmF0ZWQgU1NPIENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA24egkW+W/T6VR+IckynKqrpWxFUXFhJu4vXQnYgOgVH6BtVoEbdHlZPk/vTCPbnRbS3VBizJzvf3kQ/1OG8Q6bB94sbKW35tGb+k6rNklW1hshPCbgd+7MXT2Ky/ZtfxEY4nicOzyub84/rydQ12im3mZuRKBLjYUsd43xlaZVo40UuyV4PUiJB8a0/9E/MD3LVfQB5Hujk2VVqggQcI3vHuFVaZU2rydVrSmuTRmCkpNyBU3m374S16uD0MPkUllm//En+DKbkTQA8vU7CuiTAIiYTtzIjUTymVdcYLkOjaon4XkFcsx2+Dg31tDKr2Vf13osRvYxp3WARsLCImZQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBcFn7Rw8aGsaRE6Y3+Xlj8PXA35rzyqSA75oLaVzR2+UEU+5c1JVLbBBDw+7giSffNo0mS/OiDG7gtvtM+WTHcCLEAxEkC0gnbCi7sfaadK7Bq5CwP6mrZUgjkyQC8RpuFDGQz8GHyOkKpI8Mg/h4Dd/zUutQDuPFXoHQVowLIFOS2S6xvnQc2INXwZxxP2InhmF9Bf0kv+5KFiGmrHwEFHMTgb3RmVKZSTUUn+HZcBrTnQ6Jw1Peh7ORo+zSVGZlEjkWJdocXwDIbQde5Gh2eegjpyWzS1wfWRsa7cuA4llE6vj8ztivC21ufYu9+dldyLF3Zuib4hwSaZJ7MOaeo</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">sfrunza@myseneca.ca</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="_808ba4a2112df99f1409" NotOnOrAfter="2023-01-16T15:32:30.039Z" Recipient="https://api.telescope.cdot.systems/v1/auth/login/callback" />
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2023-01-16T14:27:30.039Z" NotOnOrAfter="2023-01-16T15:32:30.039Z">
<AudienceRestriction>
<Audience>https://api.telescope.cdot.systems/v1/auth/sp</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid">
<AttributeValue>eb34f74a-58e7-4a8b-9e59-433e4c412757</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
<AttributeValue>61e8ee88-bd7c-453f-be1d-f11778b7c191</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/displayname">
<AttributeValue>Stefan Frunza</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider">
<AttributeValue>https://sts.windows.net/eb34f74a-58e7-4a8b-9e59-433e4c412757/</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/claims/authnmethodsreferences">
<AttributeValue>http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
<AttributeValue>Stefan</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
<AttributeValue>Frunza</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
<AttributeValue>sfrunza@myseneca.ca</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>sfrunza@myseneca.ca</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement AuthnInstant="2023-01-16T14:32:27.495Z" SessionIndex="_5ffeffda-dbc1-4a3a-8e38-737a77271400">
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
</samlp:Response>
The SAML authentication is done, however as an aside if it is successful Telescope will authorize you by making a JWT for you and passing it to the front end so that you can use it in further calls as authorization to access protected routes. The URL you will likely first notice after login will look something like this:
You can actually copy and paste this access token into JWT.io as below and find the information that is stored within that is your 'passport' so to speak that will allow you access to Telescope services.
Generally the way this auth-tango works is that there is going to be a SP that would like to check an actor's credentials, it is in the actor's interest to provide the SP with verification so they can access the services they are after. The actor will have identity information stored in an IdP, this could be belonging to the same system or it could be from another trusted system that the SP could redirect to and this is where SAML comes into play. If the actor has their identity information stored in another IdP that the SP trusts they can redirect to that and allow for a SAML assertion to be generated and returned that would be proof of the actors identity along with all the claims the system would need to classify their clearance and other select personal information.
For an example you can imagine signing into the Epic Games Launcher to play Fortnite. For the sake of this example you do not have an Epic account and are instead logging-in with Google. Epic Games Launcher Client redirects to a Google log-in form and allows retrieval of your information through Google's IdP which it also trusts, google will pass back a SAML2 assertion with some of your information to a Post route the Epic Client is set to handle your user information on and you will be authenticated and allowed to play your games.
In this case...
the Service Provider is the Epic Launcher that has the games you would like to play,
and the IdP would be Google Sign-in.
For another example closer to home lets discuss Telescope.
Telescope similarly is bound to Azure Active Directory. When you request to sign in it redirects to Microsoft, once you log into Microsoft it is bound to automatically send a post back to Telescope with the user information in the format we have above. This is used to authenticate the user.
In this case the SP is Telescope,
and the IdP is Azure Active Directory/The MS Login Service.
This can also be used to illustrate the power of SSO. Lets say you are already signed into Microsoft on your browser, you are looking through your Outlook. Microsoft has already verified who you are through their IdP and they have stored a cookie that establishes the relationship between your browser and their IdP. Everytime you go to sign into a new service that uses Microsoft's accounts Microsoft's IdP (Azure AD) will know from the information on the cookie in your browser who you are and will be able to automatically generate the claims needed for you to use the next service.
So lets say once more that you want to access Telescope. You are already logged into Outlook. The cookie on your browser will be used to begin the process of prompting the IdP to send the needed claims through the bindings it has with Telescope, posting the necessary information about you to grant you access to Telescope services.
David has previously written a SAML blog when first getting it working with Telescope and has some more in-depth explanations of the endpoints you need to configure to use Seneca's SSO with Passport-SAML and Azure AD more specifically.
It is a better practical starting point, highlighting some of the important pieces to set such as an an entry point which is the URL for Seneca's IdP login to Azure AD and a callback URL which is where our servers should handle the posted result that the IdP returns. As we move forward and decide how we are going to implement SAML and SSO in starchart the implementation might be similar given that we are also using a Node back-end. It will be worth referencing this again along with the Telescope implementation.
In the final implementation of Telescope the authorization is done through a bearer token so that it can be passed across micro services through the header, in our implementation for starchart we will also have the option of using sessions, this remains to be seen.
Here is the first video in a playlist of some high level overviews of how authentication works from the folks at Azure.
The following is a link to a very good introduction to SAML particularly, unlike the above more general discussion around authentication https://www.youtube.com/watch?v=SvppXbpv-5k