Using IAM Identity Center and MFA Enforcement for AWS User Management

Introduction

This guide covers IAM Identity Center (formerly SSO) and MFA Enforcement (requiring two-factor authentication).

IAM Identity Center (SSO) is a centralized access management service. It lets you manage user identities and permissions across all your AWS accounts and business apps in one place. When combined with MFA Enforcement, you create a high-security barrier while keeping the login experience smooth for your team.

Key Benefits

  • Single Sign-On (SSO) Experience: Employees only need to remember one password to access all AWS resources via a custom portal.
  • Maximum Security with MFA: Even if a password is leaked, attackers can't get in without the physical device or MFA app.
  • Reduced Operational Risk: No more managing long-term Access Keys (which are easily leaked). These are replaced by short-lived, auto-expiring temporary tokens.


The Workflow

  1. Create a Resource Stack: Define permissions and groups, then assign permissions to those groups.
  2. Create Users: Use IAM Identity Center to add users; they will receive an invitation via email.
  3. User Setup: The user sets up their MFA and logs in via SSO to use their assigned permissions.
  4. Centralized Control: Admins can easily grant, revoke, or disable accounts from a single dashboard.


Why is this the "Gold Standard" for security?

  • Stress-free Admin: No need to manually create passwords, send keys, or manage secret files.
  • Empowered Users: Users manage their own personal info and MFA devices.
  • Instant Revocation: If an employee leaves, just disable them in the Identity Center. They immediately lose access to all accounts and roles.
  • Total Safety: No Access Keys are left lying around on hard drives or any repository.


Step-by-Step Instructions

First, create the file lib/sso-policy-group-stack.ts with the following content:

import * as cdk from "aws-cdk-lib";
import * as identitystore from "aws-cdk-lib/aws-identitystore";
import * as sso from "aws-cdk-lib/aws-sso";

export class SsoPolicyGroupStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const ssoInstanceArn = "<ssoInstanceArn>";
    const identityStoreId = "<identityStoreId>";

    const devPermissionSet = new sso.CfnPermissionSet(
      this,
      "DevPermissionSet",
      {
        instanceArn: ssoInstanceArn,
        name: "DeveloperAccess",
        sessionDuration: "PT2H",
        managedPolicies: ["arn:aws:iam::aws:policy/AmazonS3FullAccess"],
        inlinePolicy: {
          Version: "2025-01-01",
          Statement: [
            {
              Sid: "AllowS3OnlyWithMFA",
              Effect: "Allow",
              Action: "s3:*",
              Resource: "*",
              Condition: {
                BoolIfExists: {
                  "aws:MultiFactorAuthPresent": "true",
                },
              },
            },
          ],
        },
      },
    );

    const devGroup = new identitystore.CfnGroup(this, "DevGroup", {
      identityStoreId: identityStoreId,
      displayName: "AmazonS3FullAccess-Group",
    });

    new sso.CfnAssignment(this, "GroupAssignment", {
      instanceArn: ssoInstanceArn,
      permissionSetArn: devPermissionSet.attrPermissionSetArn,
      principalId: devGroup.attrGroupId,
      targetId: this.account,
      principalType: "GROUP",
      targetType: "AWS_ACCOUNT",
    });
  }
}

Explain:

  • sessionDuration: "PT2H" stands for a Period of Time of 2 hours. You can configure this duration flexibly depending on the sensitivity of the tasks the user is permitted to perform:
    • PT15M (15 minutes): For extremely sensitive operations (e.g., Deleting Databases, Root Access).
    • PT8H (8 hours): Sufficient for a standard office shift.
    • PT12H (12 hours): The typical maximum duration for developers working throughout the day.
  • devPermissionSet: I’m creating a policy that allows full access to AWS S3, but only if the account has MFA enabled.
  • devGroup & CfnAssignment: This creates a group and assigns the policy to it. Now, you just need to add a user to this group, and they will automatically inherit these permissions.
  • To find your ssoInstanceArn and identityStoreId, run this command:

> aws sso-admin list-instances
{
    "Instances": [
        {
            "InstanceArn": "<ssoInstanceArn>",
            "IdentityStoreId": "<identityStoreId>",
            "OwnerAccountId": "OwnerAccountId",
            "CreatedDate": "2026-01-30T11:28:03.626000+00:00",
            "Status": "ACTIVE"
        }
    ]
}


Next, update your bin/aws-cdk.ts file:

#!/usr/bin/env node
import * as cdk from "aws-cdk-lib/core";
import { SsoPolicyGroupStack } from "../lib/sso-policy-group-stack";

const app = new cdk.App();
new SsoPolicyGroupStack(app, "SsoPolicyGroupStack");


Managing Users

After deploying the stack to AWS, go to the IAM Identity Center console to create a User. Make sure to assign them to the correct User Group.



Once created, the user will receive an email. They should follow the link to set their password, set up MFA, and log in.


To work with AWS via the terminal, the user first needs to configure SSO:

> aws configure sso
SSO session name (Recommended): <your_user_name>
SSO start URL [None]: <sso_start_url>
SSO region [None]: ap-southeast-1
SSO registration scopes [sso:account:access]:
Attempting to automatically open the SSO authorization page in your default browser.
The only AWS account available to you is: 123416156752
Using the account ID 123416156752
The only role available to you is: DeveloperAccess
Using the role name "DeveloperAccess"
Default client Region [ap-southeast-1]: ap-southeast-1
CLI default output format (json if not specified) [None]:
Profile name [DeveloperAccess-123416156752]: my-dev-profile
To use this profile, specify the profile name using --profile, as shown:
aws sts get-caller-identity --profile my-dev-profile

Explanation:
  • SSO session name: This is the username you have created.
  • SSO start URL: You can find this value in IAM Identity Center > AWS access portal URLs. Alternatively, using the IdentityStoreId (which I showed you how to retrieve above), the URL will follow this format: https://{IdentityStoreId}.awsapps.com/start
  • Profile name: You can set this value to anything you like. When using the AWS CLI later, you will specify this profile to execute commands.


In the future, the user just needs to log back in using the created profile:

aws sso login --profile my-dev-profile

  • After logging in via SSO, AWS does not save your Access Keys into a .env file. Instead:
  • Root SSO Token: Stored in ~/.aws/sso/cache/ (as a JSON file). This token has a long duration (typically several days).
  • Temporary Credentials: When you want to use AWS, simply specify the correct profile you created. AWS will automatically use the Root Token to exchange it for a temporary Access Key/Secret Key, which is then stored in RAM or a short-term cache.


Now, the user can access services they have permission for:

> aws s3 ls --profile my-dev-profile
2026-01-17 11:01:40 bucket-name-test-cb2a91d6
2026-01-25 12:00:35 bucket-public-cb2a91d6


Happy coding!

See more articles here.

Comments

Popular posts from this blog

All practice series

Deploying a NodeJS Server on Google Kubernetes Engine

Setting up Kubernetes Dashboard with Kind

Using Kafka with Docker and NodeJS

Monitoring with cAdvisor, Prometheus and Grafana on Docker

Kubernetes Practice Series

Kubernetes Deployment for Zero Downtime

Practicing with Google Cloud Platform - Google Kubernetes Engine to deploy nginx

NodeJS Practice Series

Helm for beginer - Deploy nginx to Google Kubernetes Engine