Repository navigation
Fix device_code login getting no refresh token (sessions end after 8 hours) - #1513
Conversation
…t a refresh token AWS only issues refresh tokens to clients registered with the sso:account:access scope, but registerClient() sent it for PKCE only. Send it for both workflows, record it in RegisterClientData, and replace cached registrations that lack it. Signed-off-by: Ryo Kusnadi <ryokusnadi@gmail.com>
|
@synfinatic friendly ping on this one when you have a moment. Happy to change anything. |
…king token from an old registration is kept Signed-off-by: Ryo Kusnadi <ryokusnadi@gmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1513 +/- ##
==========================================
+ Coverage 86.56% 86.64% +0.08%
==========================================
Files 78 78
Lines 5200 5208 +8
==========================================
+ Hits 4501 4512 +11
+ Misses 472 470 -2
+ Partials 227 226 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
|
@RyoKusnadi you really should be running |
Signed-off-by: Ryo Kusnadi <ryokusnadi@gmail.com>
synfinatic
left a comment
There was a problem hiding this comment.
other than the broken CI issues and the changelog still not conforming to the existing pattern, LGTM.
Signed-off-by: Ryo Kusnadi <ryokusnadi@gmail.com>
|
Thanks for the contribution @RyoKusnadi. Typically I require all commits signed, but for first time contributors I do make an exception. |
Problem
With
AuthWorkflow: device_code(also the default over SSH/WSL),aws-sso loginstores a token with no refresh token andexpiresIn: 28800. The Identity Center session duration is ignored and you must log in again every 8 hours. PKCE logins do not have this problem.How it happens: a user sets
AuthWorkflow: device_code(or logs in over SSH), runsaws-sso login, and the stored token has an emptyRefreshToken. Path:reauthenticate()->registerClient()ininternal/sso/auth/awssso_auth.go, which registered the OIDC client with no scopes for device_code.Cause
registerClient()only setScopes: ["sso:account:access"]for PKCE. AWS only issues refresh tokens to clients registered with that scope, even ifrefresh_tokenis in the grant types (the AWS CLI sets it too, viasso_registration_scopes). AndregisterClient(force=false)reused any cached, unexpired registration, so an old device_code registration would keep getting tokens with no refresh token.Fix
registerClient()sends the scope for both workflows.RegisterClientDatarecordsScopes(like it already does forGrantTypes).registerClient(force=false)only reuses a cached registration that has the scope; otherwise it registers a new client. This is the one place registrations get reused, soAuthenticateand the Unauthorized retry path are covered too.ValidAuthToken()does not look at the scope. A still-valid token from an old registration keeps working, andlogin --forcestill logs out that session. The registration is replaced at the next real re-authentication.scopesfield but were always registered with the scope, soUnmarshalJSONfills it in. They are not replaced.SSO_ACCOUNT_ACCESS_SCOPEis now defined asstorage.SSOAccountAccessScope, so there is one source.Scope
StartPKCEAuthCodeFlowalready requests the scope; no other call site registers clients. Not covered: whether AWS then returns a refresh token for a given Identity Center instance (needs a live account).Testing
TestRegisterClientCachedScope: a cached scope-less registration is replaced (with the scope stored), one with the scope is reused, and a scope-less PKCE registration reloaded from the store file is reused.TestReauthenticateReplacesScopelessRegistration: expired token with no refresh token plus a scope-less registration; re-authentication registers a new client with the scope.TestValidAuthTokenDeviceCode: a valid token with a scope-less registration returns true and the registration is kept.TestE2ELogin_ForceScopelessRegistration: upgraded user with a valid token runslogin --force; one logout, new registration with the scope, token has a refresh token. Against the earlier version of this PR (check inValidAuthToken) it fails withexpected: 1, actual: 0logouts.TestRegisterClientDeviceCodeandTestRegisterClientDataScopesfrom the first version.Removing the scope check from
registerClientmakes the first two fail.preAuth/preAuthExpiredseed the scope, like a new registration would.Ran:
go vet,gofmt -l,go test ./...andgo test -tags e2etests ./cmd/aws-sso/(withHOMEpointed at a temp dir that has.config/aws-sso). All pass. Not run: a live AWS login (the tests use mocks only).Environment: main @ 05d203b + this branch @ 74da2b0, go1.27.1, darwin/arm64
Risk
device_code users who upgrade keep their current session. Their next re-authentication registers a new client, after which tokens come with a refresh token. To roll back, revert this PR; stored data with a
scopesfield is still readable.Fixes #1508