assume and granted sso login can't complete a device-code login against an Identity Center instance on the new dual-stack portal domain (https://<instance>.portal.<region>.app.aws). The link granted prints points at the legacy IPv4 portal on a different domain than the configured start URL, and sign-in there fails unless you already have a session on that domain.
Repro
Profile pointing at a dual-stack instance:
[profile example]
granted_sso_start_url = https://ssoins-REDACTED.portal.us-east-2.app.aws
granted_sso_region = us-east-2
granted_sso_account_id = 000000000000
granted_sso_role_name = AdministratorAccess
assume example prints:
[i] If the browser does not open automatically, please open this link: https://ssoins-REDACTED.us-east-2.portal.amazonaws.com/#/device?user_code=XXXX-XXXX
Different domain than the start URL.
Root cause
Two separate things.
granted is faithful — pkg/idclogin/run.go prints deviceAuth.VerificationUriComplete verbatim, and AWS is what returns the legacy domain. Confirmed with a raw unauthenticated call using the same start URL, where the only variable is which endpoint the request lands on:
$ aws sso-oidc start-device-authorization \
--start-url https://ssoins-REDACTED.portal.us-east-2.app.aws --region us-east-2 ...
verificationUriComplete: https://ssoins-REDACTED.us-east-2.portal.amazonaws.com/#/device?user_code=RDKV-JGVM
$ AWS_USE_DUALSTACK_ENDPOINT=true aws sso-oidc start-device-authorization ...same args...
verificationUriComplete: https://ssoins-REDACTED.portal.us-east-2.app.aws/#/device?user_code=XVNK-HVKG
So AWS returns a usable URI if the sso-oidc call goes to the dual-stack endpoint. That half is tracked upstream at aws/aws-cli#10507.
The granted-side bug is that there's no way to ask for it. pkg/cfaws/assumer_aws_sso.go:193 and pkg/granted/sso.go:311 build the client config as:
newCfg := aws.NewConfig()
newCfg.Region = rootProfile.SSORegion()
aws.NewConfig() leaves ConfigSources empty, and the SDK bails out early:
func resolveUseDualStackEndpoint(cfg aws.Config, o *Options) error {
if len(cfg.ConfigSources) == 0 {
return nil
}
...
}
(service/ssooidc/api_client.go, unchanged as of v1.35.15, the version pinned on main.)
So both AWS_USE_DUALSTACK_ENDPOINT=true and use_dualstack_endpoint = true in ~/.aws/config are dropped before they reach the client. The documented aws-cli workaround has no effect on granted.
Workaround
UseAuthorizationCode = true in ~/.granted/config. PKCE never calls StartDeviceAuthorization, so the bad URI is never produced — it registers with IssuerUrl set to the configured start URL and goes straight to oidc.<region>.amazonaws.com/authorize. Confirmed working on 0.39.0.
Worth flagging that #923 pitched PKCE purely as a UX improvement and deliberately kept device code as the default. It's also currently the only working path for dual-stack instances, which is maybe an argument for revisiting that default, or at least documenting it.
Suggested fix
Load shared config instead of a bare one, so the standard AWS env vars and ~/.aws/config settings apply:
cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(rootProfile.SSORegion()))
Same pattern applies at the other aws.NewConfig() sites (pkg/cfaws/creds.go:111, pkg/cfaws/assumer_aws_sso.go:227, pkg/granted/doctor/doctor.go:228) if AWS config is meant to be honored there too.
granted 0.39.0 (homebrew), macOS 26.5 arm64.
assumeandgranted sso logincan't complete a device-code login against an Identity Center instance on the new dual-stack portal domain (https://<instance>.portal.<region>.app.aws). The link granted prints points at the legacy IPv4 portal on a different domain than the configured start URL, and sign-in there fails unless you already have a session on that domain.Repro
Profile pointing at a dual-stack instance:
assume exampleprints:Different domain than the start URL.
Root cause
Two separate things.
granted is faithful —
pkg/idclogin/run.goprintsdeviceAuth.VerificationUriCompleteverbatim, and AWS is what returns the legacy domain. Confirmed with a raw unauthenticated call using the same start URL, where the only variable is which endpoint the request lands on:So AWS returns a usable URI if the sso-oidc call goes to the dual-stack endpoint. That half is tracked upstream at aws/aws-cli#10507.
The granted-side bug is that there's no way to ask for it.
pkg/cfaws/assumer_aws_sso.go:193andpkg/granted/sso.go:311build the client config as:aws.NewConfig()leavesConfigSourcesempty, and the SDK bails out early:(
service/ssooidc/api_client.go, unchanged as of v1.35.15, the version pinned on main.)So both
AWS_USE_DUALSTACK_ENDPOINT=trueanduse_dualstack_endpoint = truein~/.aws/configare dropped before they reach the client. The documented aws-cli workaround has no effect on granted.Workaround
UseAuthorizationCode = truein~/.granted/config. PKCE never callsStartDeviceAuthorization, so the bad URI is never produced — it registers withIssuerUrlset to the configured start URL and goes straight tooidc.<region>.amazonaws.com/authorize. Confirmed working on 0.39.0.Worth flagging that #923 pitched PKCE purely as a UX improvement and deliberately kept device code as the default. It's also currently the only working path for dual-stack instances, which is maybe an argument for revisiting that default, or at least documenting it.
Suggested fix
Load shared config instead of a bare one, so the standard AWS env vars and
~/.aws/configsettings apply:Same pattern applies at the other
aws.NewConfig()sites (pkg/cfaws/creds.go:111,pkg/cfaws/assumer_aws_sso.go:227,pkg/granted/doctor/doctor.go:228) if AWS config is meant to be honored there too.granted 0.39.0 (homebrew), macOS 26.5 arm64.