A proof-of-concept implementation of fetching AWS credentials using the OAuth2 Authorization Code Flow w/ PKCE.
Find a file
2025-10-05 09:24:33 -04:00
src Initial commit 2025-10-05 09:17:35 -04:00
.gitignore Initial commit 2025-10-05 09:17:35 -04:00
Cargo.lock Initial commit 2025-10-05 09:17:35 -04:00
Cargo.toml Initial commit 2025-10-05 09:17:35 -04:00
README.md Add PKCE docs 2025-10-05 09:24:33 -04:00

AWS SSO POC

Proof-of-concept implementation of an AWS SSO login for CLI use. This uses the same flow that the AWS CLI v2 uses to sign in via aws sso login.

Caution

Do not use this for anything security related. It follows AWS's code flow, but is a proof-of-concept and not guaranteed to be perfectly secure.

To run:

AWS_REGION="us-east-1" START_URL=https://d-1234567890.awsapps.com/start cargo run

Auth Flow

AWS uses the OAuth2 Authorization Code Flow with Proof of Key Code Exchange to login the CLI tool. The APIs they use are publicly available and somewhat documented via AWS's standard API docs and SDK docs (e.g., boto3).

  1. Register the client via a register_client endpoint
    • This requires a pre-existing "start URL" (e.g., https://d-1234567890.awsapps.com/start).
    • This also registers a redirect URI, which is where AWS redirects the user to after they authorize the tool.
    • The return of this is a payload containing a client_id.
  2. Generate a code verifier, code challenge, and state
    • Not going to describe this much as this is standard OAuth2 PKCE.
    • Verifier is a string of 32 random bytes, Base64 URL encoded
    • Challenge is a SHA256 hash of Basse64 URL encoded Verifier, then Base64 URL encoded again.
    • State is a random string returned to us on redirect, ensuring no MITM or similar issue occurred.
  3. A webserver is opened on localhost at some port (preferrably something random and ephemeral)
    • This is port recorded and kept alive until we recieve the user redirect (or some timeout)
  4. The user is directed to their browser to a specific AWS URL with details previously gathered.
    • This includes the code_challenge, which AWS saves for later.
    • The user is presented with a dialog to authorize our tool.
    • After authorizing, they're redirected to our local webserver with the authorization code and state in the query (e.g., http://localhost:56789/?code=<code>&state=<state>)
  5. The CLI tool extracts the authorization code and state.
    • We verify that the state matches what we sent.
  6. The CLI tool exchanges the authorization code for a short-lived access token using the create_token endpoint.
    • We provide the code_verifier generated earlier. AWS hashes and encodes this using the same process we did and compares it to the code_challenge sent earlier.
    • If we cannot provide a matching code_verifier, then we were not the original party who generated this request (someone snatched the authorization code)
    • This is the PKCE extension to OAuth2.
  7. The CLI fetches a list of the accounts available to this user/access token
    • Some account ID is chosen (e.g., via CLI flags or a dialog)
  8. The CLI fetches a list of the roles available to this user/access token in this account
    • Some role is chosen (e.g., via CLI flags or a dialog)
  9. The CLI uses the access token to fetch credentials for the role in its account.
    • These are standard AWS credentials, which can be passed into any of the SDKs or saved into ~/.aws/... for other tools to use.