DEV Community

Andrea Mignone
Andrea Mignone

Posted on • Originally published at imandrea.me on

Unveiling the SAML SSO Magic with AWS IAM Identity Center

If you've ever wondered about how the magic of SAML works behind the scenes, you might be in the right place. In this blog post, we'll analyze requests and responses of the SAML federation that we set up in the previous episode of this series.

Note: this post is part of a series dedicated to AWS IAM Identity Center (a.k.a. IAM IC) and related integrations. Check out all the "episodes" following the tag #aws-auth-series.

0 - The trust

First things first: we need to establish trust between IAM Identity Center and our app. Let's start by configuring the IAM Identity Center as described in the previous blog post. After that, clone this repo, and follow the instructions to get it up and running.

Next, you can download a browser extension for isolating the SAML traffic, such as:

While this extension is not a strict requirement, using a SAML-oriented extension can help filter SAML traffic and gather relevant information. It's much more convenient than inspecting all the network traffic with the browser. Just remember to open the extension before you start the SAML authentication process.

Ok, cool: we are ready to start!

1. The user tries to access the app

The SP-initiated process begins with a user who wants to access to our Node app, namely the Service Provider. The user requests a protected app URL with her browser, such as http://localhost:3000. Our app receives this request, and sends back a redirection to the local login page. The user's browser follows the redirection information, and it tries to get the URL http://localhost:3000/login.

2. The user is redirected to AWS

When the user's browser requests the /login path, a fundamental redirection happens. Let's look inside it with curl:

$ curl -I http://localhost:3000/login
HTTP/1.1 302 Found X-Powered-By:
Express Location:
https://<IAM_IDENTITY_CENTER_ENTRYPOINT_URL>?SAMLRequest=<SAMLRequest>
...
Enter fullscreen mode Exit fullscreen mode

Our app has just generated a SAML authentication request, and it is nothing but a redirection to the AWS URL we set for our Service Provider with a URL-encoded SAML Request, that is, in turn, encoded into XML. You can inspect the XML request with the SAML-tracer. Alternatively, you can decode it manually with tools like this.

Here's what a SAMLRequest looks like:

<samlp:AuthnRequest
  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  ID="_eb921ccc0cfdd887bf248173a9440ca09cd13840"
  Version="2.0"
  IssueInstant="2023-12-10T11:03:55.909Z"
  ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
  Destination="https://portal.sso.eu-central-1.amazonaws.com/saml/assertion/foo"
  AssertionConsumerServiceURL="http://localhost:3000/login/callback">

  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
    http://localhost:3000/myDemoSAMLAudience
  </saml:Issuer>

  <samlp:NameIDPolicy
  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  AllowCreate="true"
  Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/>

  <samlp:RequestedAuthnContext
  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  Comparison="exact">
    <saml:AuthnContextClassRef
      xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
      urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
    </saml:AuthnContextClassRef>
  </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>
Enter fullscreen mode Exit fullscreen mode

Let's go over the elements of that request:

  • ID: unique identifier for the request generated by our Node app
  • Version: SAML version used (2.0 in this case)
  • IssueInstant: the timestamp of this request
  • Destination: specifies the endpoint where the request should be sent
    • IAM Identity Center sign-in URL on the AWS side
  • AssertionConsumerServiceURL: is the callback URL of the SP intended to handle the SAML response from the IAM IC
    • Application ACS URL on the AWS side
  • <saml:Issuer>: is the predefined string that we set in the trust process
    • Application SAML audience on the AWS side

From the user's perspective, she is just redirected to the log in page of the IAM Identity Center

IAM IC login page

3. The IdP Response

If the user logs in correctly to IAM IC with her username and password, the IdP generates a SAML response with information about the user and the authentication process. The XML of the SAML response is more complex than the requests. Moreover, part of the information needs to be signed. It couldn't be easy to grasp relevant parts at the first sight. The response, among many other things, contains:

  • _id: unique identifier for the response generated by IAM Identity Center
  • InResponseTo: a reference to the request ID
  • Assertion: an element containing data about the user
    • Subject: a reference to the user that can be used by our App to identify the user who wants to log in (in our case the user email, see the attribute mappings in IAM IC)
    • AttributeStatement: a wrapper element containing the other user attributes defined in the attribute mappings in IAM IC
    • Conditions: the validity period of this SAML response

For the sake of convenience, we can inspect a quick summary under the Summary tab of the SAML-tracer. Still curious? We can explore the full XML under the SAML tab. I recommend again "A Developer's Guide to SAML" as a reference for an in-depth analysis.

This response is routed back to the callback URL of our app. In this case, there is not a redirection at the HTTP level, but IAM IC uses a mechanism similar to an HTML form submission, with some custom JavaScript kicking in. The final result is an HTTP POST request to http://localhost:3000/login/callback, with the SAML response in the body.

4. Logged in

Finally, the SP receives and validates the SAML response. If everything looks fine to our toy app, the user is logged in, and a dedicated session is established. In the last part of our example, the user is redirected once again to the requested protected content:

$ curl -v 'http://localhost:3000/login/callback' \
-H 'Content-Type: application/x-www-form-urlencoded' \
... \
--data-raw 'SAMLResponse=<SAMLResponse>

< HTTP/1.1 302 Found
< X-Powered-By: Express
< Location: /
...
Enter fullscreen mode Exit fullscreen mode

Wrapping up

In this example, we have explored what happens under the hood when we use IAM Identity Center as the Identity Provider for our custom app.

Note that, usually, the entire process takes place within the user's browser. The communication between the IdP and the SP is kind of like indirect and involves the user's browser as an intermediary, routing information back and forth. This means that our SP can be hosted in a private network, without being directly reachable by the Identity Provider over the Internet.

The following picture (credit: IBM) summarizes well the SAML dance steps we have just executed.

SAML Web Browser SSO Scenarios by IBM

There are many other flavors of SAML out there. I hope that this example can help you understand the actors involved and their responsibilities.

Cheers!

^..^

Top comments (0)