Enabling MFA
A password on its own is a weak gate. People reuse passwords, fall for phishing emails, and leak credentials in ways you never find out about. MFA (multi-factor authentication) fixes this by demanding a second proof of identity at sign-in — something you have (a phone or a hardware key) on top of something you know (the password). With MFA enabled, a stolen password alone is useless to an attacker. This page explains the supported MFA types, walks through turning it on for both the root user and an IAM (Identity and Access Management) user, and shows the gotcha most guides miss: how to enforce MFA with a policy instead of just hoping people enable it.
What MFA is and why it matters
Authentication factors come in categories: something you know (a password), something you have (a device), and something you are (a fingerprint). MFA simply means using more than one category. After you type your password, AWS asks for a second factor — usually a short numeric code or a tap on a security key.
The most important place to enable MFA is the root user — the all-powerful account owner created when you first signed up. The root user can close the account, change billing, and bypass most permission controls. If its password leaks and there is no MFA, an attacker owns everything. AWS now strongly nudges you toward this, and for some account types MFA on root is mandatory.
MFA is not optional for humans. Treat MFA as mandatory for the root user and for every IAM user who can sign in to the AWS Management Console (the web dashboard). A console password without MFA is a single point of failure.
Supported MFA types — which to choose
AWS supports several kinds of second factor. You can even register more than one per user as a backup.
| MFA type | What it is | Best for | Watch out for |
|---|---|---|---|
| Virtual TOTP app | A phone/desktop app (Google Authenticator, Authy, 1Password) that generates a 6-digit TOTP (time-based one-time password) every 30 seconds | Everyone — the easy, free default | Codes live on one device; losing the phone without a backup locks you out |
| Passkey / FIDO2 | A passwordless credential stored in your device or browser (Face ID, Touch ID, Windows Hello) | Modern, phishing-resistant human sign-in | Needs a compatible device/browser |
| Hardware security key | A physical key (YubiKey and similar) you plug in or tap over NFC | High-security admins, break-glass root access | Costs ~$25-$70 per key; keep a spare |
A virtual TOTP app is the simplest starting point and costs nothing. For the root user and for privileged admins, a hardware security key or passkey is stronger because it is resistant to phishing — there is no code an attacker can trick you into typing.
Enabling MFA on the root user
Sign in as the root user (using the email address you signed up with), then:
- Open the account menu at the top right and choose Security credentials.
- In the Multi-factor authentication (MFA) section, choose Assign MFA device.
- Enter a device name, pick a type (Authenticator app, Passkey or security key, or Hardware TOTP token), and choose Next.
- For an authenticator app: scan the QR code with your app, then enter two consecutive codes it generates to confirm pairing.
- Choose Add MFA. You are done — the next root sign-in will ask for a code.
Root MFA cannot be done with the CLI. The AWS CLI (Command Line Interface) can manage MFA for IAM users, but the root user’s MFA must be configured in the Console while signed in as root. Store the recovery details and any backup device somewhere safe and offline.
Enabling MFA on an IAM user
Console steps
- Open the IAM console at
https://console.aws.amazon.com/iam/. - Choose Users, click the user (for example
jane.doe), then open the Security credentials tab. - Under Multi-factor authentication (MFA), choose Assign MFA device.
- Name the device, pick the MFA type, and choose Next.
- Scan the QR code (for an app) or follow the prompts (for a security key/passkey), then enter the verification code(s).
- Choose Add MFA.
A best practice is to let users enable their own MFA. You grant them a small self-service policy, send them the sign-in link, and they register a device on first login.
CLI for a virtual MFA device
First create the virtual device. The QR code is returned as a PNG you decode, scan, then confirm:
aws iam create-virtual-mfa-device \
--virtual-mfa-device-name jane.doe \
--outfile /tmp/jane-qr.png \
--bootstrap-method QRCodePNG
Output:
{
"VirtualMFADevice": {
"SerialNumber": "arn:aws:iam::123456789012:mfa/jane.doe"
}
}
Scan /tmp/jane-qr.png with an authenticator app, then bind the device to the user by submitting two consecutive codes:
aws iam enable-mfa-device \
--user-name jane.doe \
--serial-number arn:aws:iam::123456789012:mfa/jane.doe \
--authentication-code1 123456 \
--authentication-code2 789012
This command produces no output on success. The user must now provide an MFA code when signing in to the Console.
The gotcha: enforce MFA with a policy
Enabling MFA on a device only allows MFA — it does not require it. A user with a password can still skip the setup and keep working. To actually force it, attach a policy that uses the aws:MultiFactorAuthPresent condition key. This denies sensitive actions unless the current session was authenticated with MFA, while still letting the user manage their own MFA device so they can get set up.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowManageOwnMFA",
"Effect": "Allow",
"Action": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ResyncMFADevice"
],
"Resource": [
"arn:aws:iam::123456789012:mfa/${aws:username}",
"arn:aws:iam::123456789012:user/${aws:username}"
]
},
{
"Sid": "DenyEverythingElseWithoutMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ResyncMFADevice",
"iam:GetUser",
"iam:ChangePassword"
],
"Resource": "*",
"Condition": {
"BoolIfExists": { "aws:MultiFactorAuthPresent": "false" }
}
}
]
}
The Deny statement is the enforcer: if aws:MultiFactorAuthPresent is false, almost everything is blocked. The small Allow list (plus the carve-outs in NotAction) is what lets a brand-new user log in and register a device. BoolIfExists makes the check behave sensibly for credential types where the key is absent.
Use a Deny, not an Allow. Only an explicit
Denyreliably blocks users who already have other permissions. “Encouraging” MFA through documentation does not work — a policy condition is the only thing that truly stops a non-MFA session from doing damage.
Cost note
MFA itself is free — AWS does not charge for assigning virtual, passkey, or hardware MFA devices, and there is no per-sign-in fee. The only cost is hardware: a physical security key runs roughly $25-$70, while authenticator apps are free. Given that a single compromised root account can lead to thousands of dollars of fraudulent usage, MFA is the cheapest security control you will ever add.
Best Practices
- Enable MFA on the root user first, then lock the root credentials away and use it almost never.
- Require MFA for every IAM user that has a console password — make it non-negotiable.
- Enforce MFA with an
aws:MultiFactorAuthPresentpolicy condition; do not rely on people opting in. - Use phishing-resistant factors (hardware security keys or passkeys) for privileged admins and root.
- Register a backup MFA device, or store recovery details safely, so a lost phone does not lock you out.
- Prefer IAM Identity Center for human sign-in, where MFA can be enforced centrally across all accounts.
- Audit regularly with the IAM credential report to find any user that still lacks an MFA device.