<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yoonsoo Park</title>
    <description>The latest articles on DEV Community by Yoonsoo Park (@yoonsoo).</description>
    <link>https://dev.to/yoonsoo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2708928%2F10649c02-35c9-4a37-a7eb-76a6f1755474.png</url>
      <title>DEV Community: Yoonsoo Park</title>
      <link>https://dev.to/yoonsoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yoonsoo"/>
    <language>en</language>
    <item>
      <title>Setting Up SSO Between AWS Cognito and Salesforce</title>
      <dc:creator>Yoonsoo Park</dc:creator>
      <pubDate>Fri, 18 Apr 2025 04:00:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/setting-up-sso-between-aws-cognito-and-salesforce-15af</link>
      <guid>https://dev.to/aws-builders/setting-up-sso-between-aws-cognito-and-salesforce-15af</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Learn how to implement Single Sign-On between AWS Cognito and Salesforce for a seamless user experience with complete step-by-step instructions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-identity-provider.html" rel="noopener noreferrer"&gt;AWS Cognito Identity Provider Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Single Sign-On (SSO) between AWS Cognito and Salesforce can eliminate multiple login prompts. This guide will walk through the complete setup process, core concepts and implementation details for someone dives into the sso setup for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding AWS Cognito Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  User Pools: The base of authentication
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;User Pool&lt;/strong&gt; is Cognito's user directory that handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User registration and account creation&lt;/li&gt;
&lt;li&gt;Authentication (username/password validation)&lt;/li&gt;
&lt;li&gt;User attributes storage (email, phone, custom fields)&lt;/li&gt;
&lt;li&gt;Security features (MFA, password policies)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of a User Pool as your base database of users which answers the "who are you?" part of authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  App Clients: The Connectors
&lt;/h3&gt;

&lt;p&gt;Many beginners wonder why App Clients are needed when User Pools already manage users. (at least it was for me) Let's break it down:&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;App Client&lt;/strong&gt; defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which applications can use your User Pool&lt;/li&gt;
&lt;li&gt;What authentication flows are allowed (e.g., user password, refresh tokens)&lt;/li&gt;
&lt;li&gt;Token expiration settings&lt;/li&gt;
&lt;li&gt;Callback URLs (where users return after authentication)&lt;/li&gt;
&lt;li&gt;OAuth scopes (what user information can be accessed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;App Clients act as bridges between your applications and the User Pool that is answering the "how" and "where" authentication happens.&lt;/p&gt;

&lt;h3&gt;
  
  
  External Identity Providers (IdPs)
&lt;/h3&gt;

&lt;p&gt;When you connect external providers like Google to your User Pool, you're creating a "federation" where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users authenticate with their existing accounts&lt;/li&gt;
&lt;li&gt;Cognito receives verification from the external provider&lt;/li&gt;
&lt;li&gt;Cognito creates or maps to a user in its User Pool&lt;/li&gt;
&lt;li&gt;Cognito issues its own tokens for your applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Authentication Flow Overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6i3fw6drogegs3y59yo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6i3fw6drogegs3y59yo.png" alt="Authentication Sequence Diagram" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Configuration Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Configuring AWS Cognito
&lt;/h3&gt;

&lt;h4&gt;
  
  
  User Pool Setup
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Create or use an existing User Pool&lt;/li&gt;
&lt;li&gt;Ensure your external IdP (Google) is already configured&lt;/li&gt;
&lt;li&gt;Note your &lt;strong&gt;User Pool ID&lt;/strong&gt; (format: &lt;code&gt;region_alphanumeric&lt;/code&gt; e.g. &lt;code&gt;us-east-1_1234567890&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Locate and save your &lt;strong&gt;User Pool Domain&lt;/strong&gt; (format: &lt;code&gt;https://your-domain.auth.region.amazoncognito.com&lt;/code&gt; e.g. &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com&lt;/code&gt;)

&lt;ul&gt;
&lt;li&gt;where to find it: your User Pool &amp;gt; Branding &amp;gt; Domain&lt;/li&gt;
&lt;li&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ue3svz6blskvkxge2c0.png" alt="Find Domain from Cognito" width="800" height="447"&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  App Client Configuration
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Create a new App Client in your User Pool&lt;/li&gt;
&lt;li&gt;Enable the OAuth 2.0 flows (Authorization code grant)&lt;/li&gt;
&lt;li&gt;Add Salesforce's callback URL as an allowed callback (we'll get this later; I promise :) )&lt;/li&gt;
&lt;li&gt;Enable the necessary OAuth scopes:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;openid&lt;/code&gt; (required)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;profile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Save your &lt;strong&gt;App Client ID&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Note the full &lt;strong&gt;OAuth Endpoints&lt;/strong&gt; from the App Integration &amp;gt; App client settings page

&lt;ul&gt;
&lt;li&gt;e.g.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Endpoint&lt;/strong&gt;: &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com/oauth2/authorize&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Endpoint&lt;/strong&gt;: &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com/oauth2/token&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Info Endpoint&lt;/strong&gt;: &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com/oauth2/userInfo&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Configuring Salesforce
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create Auth Provider in Salesforce
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Go to Setup &amp;gt; Identity &amp;gt; Auth. Providers&lt;/li&gt;
&lt;li&gt;Create a new Auth Provider of type &lt;strong&gt;OpenID Connect&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;myFederatedIdP&lt;/code&gt; (or your preferred name)&lt;/li&gt;
&lt;li&gt;Enter details from Cognito:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consumer Key&lt;/strong&gt;: Your Cognito App Client ID (e.g. &lt;code&gt;1234567890&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumer Secret&lt;/strong&gt;: Your Cognito App Client Secret (e.g. &lt;code&gt;1234567890&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorize Endpoint URL&lt;/strong&gt;: The OAuth authorization endpoint from Cognito (e.g. &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com/oauth2/authorize&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Endpoint URL&lt;/strong&gt;: The OAuth token endpoint from Cognito (e.g. &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com/oauth2/token&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Info Endpoint URL&lt;/strong&gt;: The OAuth userinfo endpoint from Cognito (e.g. &lt;code&gt;https://my-domain.auth.us-east-1.amazoncognito.com/oauth2/userInfo&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default Scopes&lt;/strong&gt;: &lt;code&gt;openid email profile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Error URL&lt;/strong&gt;: Your error handling page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registration Handler&lt;/strong&gt;: Your custom Apex class (required for Salesforce to register/find users)

&lt;ul&gt;
&lt;li&gt;Salesforce automatically creates a default one for you if you toggle the switch on.

&lt;ul&gt;
&lt;li&gt;You can customize it to your needs!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Make sure you have this Apex class by going to Setup &amp;gt; Apex Classes and search for e.g. &lt;code&gt;CognitoRegistrationHandler&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Execute Registration As&lt;/strong&gt;: A designated Salesforce user&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Save the configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Update Cognito with Salesforce Callback URL
&lt;/h4&gt;

&lt;p&gt;After creating the &lt;code&gt;Auth. Provider&lt;/code&gt; in Salesforce, it will generate callback URLs. Find the &lt;strong&gt;Callback URL&lt;/strong&gt; (format: &lt;code&gt;https://your-domain.my.salesforce.com/services/authcallback/myFederatedIdP&lt;/code&gt;).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Return to AWS Cognito Console&lt;/li&gt;
&lt;li&gt;Open your User Pool &amp;gt; App clients&lt;/li&gt;
&lt;li&gt;Select your App client&lt;/li&gt;
&lt;li&gt;Add this Salesforce callback URL to the "Callback URLs" field&lt;/li&gt;
&lt;li&gt;Save the changes&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Implementing the Redirect in Your Application
&lt;/h3&gt;

&lt;p&gt;Using the redirect service pattern from the WebApp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// When a user clicks to access Salesforce:&lt;/span&gt;
&lt;span class="c1"&gt;// redirectWithToken is a function that you can implement in your application&lt;/span&gt;
&lt;span class="nx"&gt;RedirectService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirectWithToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;relayState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://your-salesforce-domain.my.salesforce.com/lightning/page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// this is where you want to redirect the user after authentication&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// In the redirect service:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getAccessToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// From cookies&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;relayStateUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;relayState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sfDomain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;relayStateUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;relativePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;relayStateUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;relayStateUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;relayStateUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Redirect to Salesforce SSO endpoint&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redirectUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sfDomain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/services/auth/sso/myFederatedIdP`&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="s2"&gt;`?startURL=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redirectUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Pitfalls and Solutions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token Format Issues&lt;/strong&gt;: Ensure your Cognito tokens include required user claims&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Callback URL Mismatch&lt;/strong&gt;: Verify exact match between Salesforce and Cognito URLs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relative Path Requirements&lt;/strong&gt;: Salesforce needs relative paths in the startURL parameter (e.g. &lt;code&gt;/lightning/page&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Scopes&lt;/strong&gt;: Verify &lt;code&gt;openid&lt;/code&gt; scope is enabled for proper OIDC authentication&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping it up 👏
&lt;/h2&gt;

&lt;p&gt;Working on SSO is quite challenging because every bit of information should be correct and match. Even if one of them is off, it won't work.&lt;br&gt;
But the advantage of SSO is that once you set it up, it will improve user experience and reduce the number of login prompts which is huge.&lt;br&gt;
I hope this guide helps you to understand the core concepts and implementation details of SSO between AWS Cognito and Salesforce.&lt;/p&gt;

&lt;p&gt;Cheers! 🍺&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.sphereinc.com/blogs/how-to-build-sso-solution-on-top-of-amazon-cognito/" rel="noopener noreferrer"&gt;How to Build SSO Solution on Top of Amazon Cognito&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-oidc-flow.html" rel="noopener noreferrer"&gt;Cognito User Pools OIDC Flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/51782571/login-with-salesforce-using-aws-cognito-openid-connect" rel="noopener noreferrer"&gt;Login with Salesforce using AWS Cognito OpenID Connect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salesforce.stackexchange.com/questions/317978/what-is-the-difference-between-relaystate-and-redirect-uri" rel="noopener noreferrer"&gt;What is the difference between relayState and redirect_uri?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.miniorange.com/iam/login-with-external-idp/configure-aws-cognito-sso" rel="noopener noreferrer"&gt;login with external idp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sso</category>
      <category>cognito</category>
      <category>salesforce</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
