Skip to content

Unveiling the SAML SSO Magic with AWS IAM Identity Center

Posted on:December 10, 2023 at 04:30 PM

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.

Table of contents

Open Table of contents

SAML, how it works

SAML is a common protocol for authentication and authorization. It’s often used to enable Single Sign-On (SSO), and it’s extremely popular at the enterprise level. With SSO a user can utilize one set of credentials to log in to many applications. If you are not familiar with SAML, I recommend “A Developer’s Guide to SAML”, a very cool YouTube video introducing SAML and related concepts.

In this post, we are going to explore a Service Provider-initiated flow. In this scenario, the Service Provider (SP) starts the authentication process, then it relies on the Identity Provider (IdP) to federate the authentication.

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>
...

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>

Let’s go over the elements of that request:

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:

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: /
...

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!

^..^