AWS credentials from a browser-based SAML sign-in — a drop-in replacement for saml2aws login with the Browser provider.
samlgate opens your IdP sign-in (Microsoft Entra ID, Okta, Google Workspace, …) in a real browser, catches the
SAML assertion on its way to AWS, exchanges it for temporary credentials with STS, and writes them to
~/.aws/credentials in the same format saml2aws uses. The Windows release is a single ~7 MB native binary with no runtime,
no Playwright and no browser-driver downloads.
It is built for teams that:
- work in one or a few AWS accounts handed to them by a parent organisation or partner, so IAM Identity Center is not an option, and
- manage people in Microsoft Entra ID using the AWS Single-Account Access enterprise app (SAML), where sign-in means a browser, MFA and Conditional Access — not a username/password prompt in a terminal.
SAML has no localhost callback. After sign-in the IdP makes the browser POST the SAMLResponse to the fixed AWS
endpoint https://signin.aws.amazon.com/saml. samlgate:
- starts Edge/Chrome with a dedicated profile and the DevTools Protocol enabled,
- intercepts exactly that ACS request (aws, aws-cn and aws-us-gov partitions) — it never reaches AWS,
- answers it with a local "you can close this window" page and closes the browser,
- calls STS
AssumeRoleWithSAMLand writes the profile.
Because the dedicated profile keeps the IdP's cookies, you sign in once; after that, renewing expired credentials just flashes a browser window for a few seconds. (Answer "Yes" to "Stay signed in?" on the first Entra sign-in — samlgate closes the browser every time, so a session-only cookie would be lost.)
Windows and macOS. Login has been verified on Windows 11 x64 and an Apple Silicon MacBook Pro. Packaged releases are currently Windows x64 and ARM64 only; macOS users can build from source as described below. The macOS 14+ native WebView backend remains experimental, as does Linux support (see Roadmap).
Download samlgate-<version>-win-x64.zip (or win-arm64) from
Releases and extract samlgate.exe into a folder on your PATH.
To build from source: dotnet publish src/Samlgate -c Release -r win-x64 (.NET 10 SDK and the Visual Studio
"Desktop development with C++" workload for NativeAOT).
Requirements: Microsoft Edge, which ships with Windows — or Google Chrome, Brave, Chromium or Whale.
Login has been confirmed on an Apple Silicon MacBook Pro. The source-build instructions below use the experimental native WebView backend (macOS 14+).
With .NET 10 and Xcode command-line tools installed, build for your Mac's architecture:
dotnet publish src/Samlgate -c Release -r osx-arm64 -o out
# Use osx-x64 on an Intel Mac. Keep both output executables together.
./out/samlgate login --browser webview--browser webview opens an AppKit window backed by WKWebView; no Chromium installation or DevTools port is needed. It requires macOS 14+ and a user-controlled graphical desktop. Sign in directly in the window. Save the backend with samlgate configure --browser webview --url "<IdP sign-in URL>". Chromium remains the default; --browser-path applies only to Chromium.
The companion samlgate-webview executable cancels the AWS ACS POST before reading its submitting form. The assertion travels to the CLI over a private child-process pipe and then to STS; it is not written to disk or printed by login. The backend supports AWS partition/regional ACS URLs and target_url, and fails closed if the form cannot be read. It does not add headless login or automatic browser fallback.
The native browser uses a separate persistent WebKit data store, identified by SAMLGATE_DATA_DIR/browser/webview/webkit-profile-id. WebKit manages the website data outside SAMLGATE_DATA_DIR; it is separate from Safari and Chromium. Keep that identifier to reuse the same session. Deleting it selects a new store but does not erase the old store. To erase this backend's store, close its windows and run samlgate-webview --remove-profile <UUID-from-webkit-profile-id> before deleting the identifier. This touches only that named store.
Session reuse and passkey availability depend on the OS, IdP and its policies. Local native login does not establish that a cloud environment can perform user-controlled authentication or use the same passkey provider.
# 1. Save your IdP-initiated sign-in URL (see "Finding the sign-in URL" below)
samlgate configure --url "https://launcher.myapps.microsoft.com/api/signin/<app-id>?tenantId=<tenant-id>"
# 2. Sign in — writes the [saml] profile to ~/.aws/credentials
samlgate login
# 3. Use it
aws sts get-caller-identity --profile saml
samlgate statusAlready using saml2aws? Skip step 1 — samlgate reads the same account from ~/.saml2aws when ~/.samlgate does
not have it.
Entra admin center → Enterprise applications → your AWS app → Properties → User access URL. Users can also right-click the app tile in My Apps and copy the link.
| Command | |
|---|---|
samlgate login |
Sign in if the stored credentials expire within 5 minutes (or --force), then print the session. |
samlgate status |
Print the session; exit code 0 if valid, 1 otherwise. Handy in scripts. |
samlgate configure --url … |
Create/update an account in ~/.samlgate. |
samlgate credential-process |
Print credentials as credential_process JSON, signing in if needed. |
samlgate exec -- <cmd> … |
Run a command with AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN set. |
Common options: -a/--idp-account <name> (config section, default default), -p/--profile <name> (credentials
profile, default saml), --role <arn>, --region, --session-duration <seconds>, --browser edge|chrome|brave|chromium|whale|webview,
--browser-path <exe>, --timeout <seconds>. Run samlgate <command> --help for the full list.
Chrome, Edge, Brave, Chromium and Whale use the same CDP capture backend. Use --browser whale to select Whale, or --browser-path for an executable outside the usual installation locations. Browser/vendor policies still need to permit CDP.
# Explicit language selection can help when an IdP's localized assets fail to load.
samlgate login --browser chrome --browser-language en-US
# Revisit the IdP even if current AWS credentials are valid; try the stored session first.
samlgate login --browser chrome --browser-mode auto --browser-language en-US --force
# Save preferences for future logins.
samlgate configure --url "<IdP sign-in URL>" --browser chrome --browser-language en-US --browser-mode autoThe default remains an interactive window with no language override. No language is automatically forced for a particular IdP. --browser-language accepts one language tag; remove browser_language from the account configuration to return to the browser default.
In auto mode, a profile that already exists is tried with --headless=new. If no SAML arrives before --silent-timeout (default 20 seconds), that browser is closed before an interactive browser opens on the same profile. A new profile goes directly to an interactive window. The silent attempt and interactive sign-in share --timeout; caller cancellation, browser launch failures and malformed ACS responses do not trigger fallback. Valid AWS credentials still skip browser login unless --force is used.
Silent refresh does not enter passwords, approve passkeys or bypass IdP policies. Reauthentication requires a user-controlled graphical browser; this option does not provide SSH/cloud user handoff. The native webview backend rejects Chromium language/auto preferences instead of silently ignoring them. Native and Chromium sessions are separate.
The SAML response lists every AWS IAM role your user is assigned in the IdP app. With one role samlgate uses it;
with several it asks (and remembers your choice per account). Pin one with role_arn / --role.
Point a different profile at samlgate (a profile that also has static keys in ~/.aws/credentials would use
those instead):
# ~/.aws/config
[profile work]
credential_process = samlgate credential-process -a default
region = ap-northeast-2When no terminal is attached, samlgate cannot ask for a role — set role_arn, or run samlgate login once so it
remembers your choice.
~/.samlgate (override with SAMLGATE_CONFIG) is an INI file with one section per account. Key names match
saml2aws, so you can copy ~/.saml2aws as-is; unknown keys are ignored.
| Key | Default | |
|---|---|---|
url |
— | IdP-initiated sign-in URL. saml2aws provider = AzureAD + app_id is converted automatically. |
aws_profile |
saml |
Credentials profile to write. |
role_arn |
— | Role to assume without asking. |
region |
partition default (us-east-1) |
STS region. |
aws_session_duration |
assertion's SessionDuration, else 3600 |
Falls back to 3600 if the role's maximum is lower. |
credentials_file |
~/.aws/credentials |
Also honours AWS_SHARED_CREDENTIALS_FILE. |
browser_type |
auto-detected Chromium | edge/msedge, chrome, brave, chromium, whale, or experimental webview (macOS 14+). |
browser_executable_path |
auto-detected | |
browser_language |
browser default | Optional single language tag, such as en-US; Chromium only. |
browser_mode |
interactive |
auto attempts a short headless refresh of an existing Chromium profile, then opens a window if needed. |
silent_timeout |
20 |
Silent attempt limit in seconds, within the overall sign-in timeout. |
target_url |
AWS ACS URLs | Additional URL to intercept (custom ACS). |
The credentials profile contains aws_access_key_id, aws_secret_access_key, aws_session_token,
aws_security_token, x_principal_arn and x_security_token_expires, exactly like saml2aws.
SAMLGATE_DATA_DIR moves the browser profiles and remembered roles (default %LOCALAPPDATA%\samlgate).
- The SAML assertion is only sent to AWS STS. The intercepted ACS request is answered locally.
- The Chromium browser profile is separate from your everyday profile and lives in the data directory; delete it to sign out. Native WebKit data uses the named store described in the macOS section.
- The credentials file is written atomically.
- Chromium DevTools listens on a random port bound to
127.0.0.1only while samlgate is running. The native WebView does not open a DevTools port. - No telemetry.
- Package and harden the experimental macOS WKWebView backend; optional fallback when Chromium is unavailable
- Linux
- Firefox via WebDriver BiDi
- Harden optional Chromium auto refresh across more IdPs and platforms
dotnet test samlgate.slnx # unit tests + a headless-browser capture test if Edge/Chrome is installed
dotnet run --project src/Samlgate -- helpsrc/Samlgate.Core holds everything testable (config, SAML parsing, STS, credentials file, DevTools capture);
src/Samlgate is the thin CLI (System.CommandLine). STS is called through AWSSDK.SecurityToken.
ISamlCapture separates the browser backend from LoginFlow. On macOS, the Core build compiles native/macos/SamlgateWebView.swift with the system Swift compiler and copies the helper to CLI/test/publish output. Other platforms do not build it. Native tests use only local synthetic pages, require a macOS 14+ desktop, and are skipped on other platforms. Use dotnet test --filter 'Category!=NativeBrowser' on a Mac without a graphical session.