Repository navigation
fix(okta): random per-install device token (#23) - #29
Conversation
The Okta device token was predictable (okta_<user>_saml2aws). Each install now generates a random token and stores it in the keychain.
|
Security second review (Sonnet): CHANGES (Medium). The legacy okta__saml2aws fallback stays predictable on installs with no keychain. The maintainer has now decided: with no keychain, keep a random token in a 0600 file under the saml2aws config directory. Also: warn the user when the save fails, and generate a new token only when none is found, so a transient keychain error doesn't rotate it. Add tests for both paths. |
…ent errors (#23) With no keychain, or when saving to it fails, the random device token is now kept in a 0600 file under the saml2aws config directory instead of falling back to the predictable okta_<user>_saml2aws value. A new token is generated only when none is found, and a failed save is reported to the user.
|
Review changes made at d2e7c3d. With no keychain, the device token is kept in a 0600 file under the saml2aws config directory, so there's no predictable fallback any more. A new token is generated only on not-found, and a failed save warns the user. Tests added. Sonnet security re-review and e2e are in progress. |
|
e2e PASS and e2e-aws PASS at d2e7c3d (2026-10-20). The Sonnet security re-review is in progress. |
|
Sonnet security re-review: APPROVE at d2e7c3d. The predictable fallback is gone, the file is created 0600 in a 0700 directory, only not-found rotates the token (mutation-checked), and a failed save warns. Low follow-ups: create the file with O_EXCL|O_NOFOLLOW to close the TOCTOU and symlink window, and tighten an existing loose ~/.aws/saml2aws (same as #33). |
fix(okta): random per-install device token (closes #23)
Record: #23 (upstream PR Versent#1484).
Problem
The Okta
DT(device token) cookie wasokta_<username>_saml2aws. Anyone who knows a user's login can derive it, which weakens Okta's "remember this device" MFA bypass.Change
deviceToken()inpkg/provider/okta/okta.gogenerates a random UUID on first use and stores it in the credential store under<idp url>/deviceToken, the same way the Okta session cookie is stored. Later runs read it back, so the token stays stable for each install and IdP.setDeviceTokenCookieuses it.After the security review
The maintainer's decisions from the review:
0600file under the saml2aws config directory (~/.aws/saml2aws/okta-device-token-<sha256(idp url)[:16]>, the directory the browser provider already uses), and later runs reuse it. If the file can't be read or written, a random token is used for that run only, with a warning.credentials.IsErrCredentialsNotFound(err). Any otherGeterror (for example a locked keychain) leaves the stored token alone. That run uses the file token and logs a warning.Geterrors and file problems are logged at warning level, not debug.Compatibility
Tests
New tests in
pkg/provider/okta/okta_devicetoken_test.go. A packageTestMainpoints the token file directory at a temp dir, so no test writes to the real~/.aws/saml2aws.TestDeviceTokenIsRandomAndStable: the token isn't derived from the username, is saved in the store, is reused, and differs between installs.TestDeviceTokenFileFallbackWithoutCredentialStore: with no store, a random token is written to a0600file (the mode isn't checked on Windows) and read back on the next run.TestDeviceTokenTransientGetErrorDoesNotRotate: aGeterror other than not-found leaves the stored token unchanged and logs a warning.TestDeviceTokenSaveErrorWarnsAndUsesFile: a failed save logs a warning, never falls back to the predictable token, and the file token is reused on later runs.TestSetDeviceTokenCookie(existing): now asserts the token is not the legacy value.Evidence:
TestSetDeviceTokenCookiefail. With this change all of them pass.go test ./...: 26 packages pass.pkg/provider/browserfails, the same as on master (Playwright CDN, uplift: playwright-go driver download broken (retired CDN), Browser provider #4/uplift: playwright-go v0.6201.1, carried from Versent#1542 (#4) #10).GOOS=windows,darwin/arm64andlinux/arm64builds of./cmd/saml2awspass.make -C test/e2e unit/e2e.