Device code phishing and what it means for AWS
You open Slack and see a message from someone claiming to be on your platform team: "Quick favor, go to the AWS sign-in page, it'll show a code, type XXXX-XXXX and approve it so I can finish setting up your access." The
You open Slack and see a message from someone claiming to be on your platform team: "Quick favor, go to the AWS sign-in page, it'll show a code, type XXXX-XXXX and approve it so I can finish setting up your access." The page it points to is real. The login screen is real. Your password and your MFA prompt are real. And yet, if you type that code in, the session that gets created does not belong to you anymore.
That's device code phishing, and it rides on a legitimate part of OAuth called the device authorization flow. AWS uses this flow in a few places, so it's worth understanding how it works, where it shows up, and what actually stops it.
What is the device authorization flow
The device authorization flow is defined in RFC 8628. It was built for devices that are awkward to type on: smart TVs, CLI tools, IoT boxes.
A familiar example is logging into Netflix or YouTube on a smart TV. The TV shows a short code and a URL. You open that URL on your phone, type the code, and sign in there instead. A few seconds later, the TV logs in on its own.
Here's what happens behind that screen. The TV (the client) asks an authorization server for a device code. The server hands back two codes: a long one the TV keeps to itself, and a short one meant for a human, the "user code." While you're typing that user code into your phone's browser and logging in normally, the TV keeps polling the server in the background, asking "has it been approved yet?" The moment you finish logging in on your phone, the server hands the TV a valid access token.
The whole design rests on one assumption: the device that requested the code and the device that approves it don't have to be the same one.
Where AWS uses the device flow
The most common place is aws sso login, used with AWS IAM Identity Center. Run that command and a browser opens asking you to confirm a code, which is the device flow in action.
Under the hood, the sso-oidc service handles this through three API calls.
-
RegisterClientregisters the CLI as a client -
StartDeviceAuthorizationissues the device code, user code, and verification URL -
CreateTokenis what the CLI polls, and it returns a token once the user has approved the request
That said, the default behavior changed in May 2024. IAM Identity Center added support for PKCE (Proof Key for Code Exchange), an authorization code flow that completes entirely in a browser on the same device. Starting with AWS CLI 2.22.0, PKCE is the default, and the device flow only kicks in if you pass --use-device-code explicitly, meant for machines without a browser. Any CLI tool or IDE extension on a current version is likely going through the PKCE path first.
Defending against it in AWS
A device code phishing attack needs three things to work: the attacker can start a device flow, the victim is willing to type the code into a real login page, and the tenant doesn't restrict the flow.
The single most effective move is upgrading the AWS CLI to 2.22.0 or later and auditing any scripts or machine images still pinned to --use-device-code. Once PKCE is the default, the authorization URL has to be opened on the same device you're signing in from, which removes the second-device approval step that device code phishing depends on.
For whatever --use-device-code usage still has to stay, for example headless or browserless hosts, IAM Identity Center on its own still has no dedicated switch to block the device code flow, and no built-in device-level restriction on the access portal. What's actually available there:
- Federate with an external IdP such as Entra ID and let conditional access on that side block the flow before it ever reaches AWS
- Configure the Identity Center SSO token provider to require that external IdP authentication
- Use a deny policy keyed on
aws:UserAgentto restrict unexpected clients, though this condition key can be spoofed by the caller and isn't a strong control on its own - Watch CloudTrail for
StartDeviceAuthorizationandCreateTokenevents onsso-oidc.amazonaws.com, and flag unusual source IPs or user agents
So AWS's main defense here has effectively shifted to the PKCE migration itself. Whatever device flow usage remains still depends on an external IdP's conditional access, or on catching it after the fact in CloudTrail.
How this differs from a normal console login
Signing in as an IAM user or root user, with password plus MFA, happens entirely in one browser session on one device. There's no second device involved, so the device flow's core mechanic, requesting a code on one machine and approving it on another, simply doesn't apply here.
That doesn't make it immune to everything. A real-time relay attack (adversary-in-the-middle, or AiTM) can still sit between a victim and the real login page, forwarding a password and a TOTP code as they're typed. A standard six-digit MFA code doesn't help much against that; it's the kind of attack a hardware passkey is built to stop.
How this differs from signing in to Amazon Connect Customer or Kiro
Amazon Connect Customer (the product formerly known as Amazon Connect, renamed in April 2026) handles agent sign-in through either its own username and password system or SAML 2.0 SSO via IAM Identity Center. Both happen as a browser redirect within one session, not a second-device approval.
Kiro, AWS's AI IDE, works the same way for its documented sign-in path. Choosing "Login with AWS Builder ID" opens your default browser, you enter your email and password there, and you're redirected back to the IDE. That's a standard OAuth authorization code flow, not the device flow. Some third-party proxy tooling has been reported to use Builder ID's device-code option as an alternative, but that's not how Kiro itself signs you in.
Does a passkey stop this
A passkey works by signing a one-time "challenge" from the server with a private key stored on your device. That signature is bound to the origin, the actual domain you're talking to, which is exactly why it holds up against AiTM relay attacks. A fake site can't get a valid signature for the real domain, full stop.
Device code phishing doesn't try to forge that signature. The victim really is on the real domain, completing a real passkey authentication. What a passkey confirms is "this device's owner authenticated to this site." It says nothing about which session that authentication was meant to approve. One write-up documents a test run where a passkey-protected account was taken over through exactly this flow, with the passkey working exactly as designed the whole time.
How Microsoft and Google handle it
Microsoft Entra ID has a direct answer: a conditional access policy with an "Authentication Flows" condition that can block the device code flow by name. Reports suggest Microsoft began rolling out a managed conditional access policy for this around February 2025. The same condition can also block authentication transfer, the feature that lets someone hand off a sign-in from a PC to a phone. One caveat: a policy scoped to users won't catch calls from service principals, those need a separate conditional access policy for workload identities.
Google Cloud and Google Workspace take a different route. I couldn't find a dedicated toggle to block the device code flow outright. Instead, reports indicate Google scopes down what that flow can reach in the first place, keeping it away from core APIs like Gmail and Drive. Context-aware access can add identity and device-based conditions on top of that, though it doesn't cover every client, mobile Gmail among them. I'll flag that this part is based on secondary sources rather than Google's own documentation, so treat it as a starting point rather than a settled fact.
Line them up and the pattern is clear. Entra ID blocks the flow outright. Google narrows what it can reach. AWS doesn't have an equivalent switch on IAM Identity Center itself, but its 2024 PKCE rollout pushes most normal usage away from the device flow by default instead.
What you can do right now
Four things are worth doing before anything more elaborate.
- Upgrade the AWS CLI to 2.22.0 or later and check whether any scripts or images still force
--use-device-code. Of everything on this list, this one closes off the most - If IAM Identity Center is federated with an external IdP, turn on conditional access there to block or at least audit device code flow usage
- Set up CloudTrail monitoring for
sso-oidcevents and watch for CLI logins from unexpected sources - Tell your team, in plain terms, not to type an authentication code into a login page unless they started that login themselves
I'm planning to actually run this attack against a sandboxed AWS environment, see what shows up in CloudTrail, and test how much of the above actually stops it. That'll be a follow-up post.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.
