Skip to content

fix: include auth scheme in Cargo credentials - #394

Merged
cloudsmith-iduffy merged 1 commit into
fix/macos-keychain-promptsfrom
fix/cargo-credential-auth-scheme
Aug 26, 2026
Merged

fix: include auth scheme in Cargo credentials#394
cloudsmith-iduffy merged 1 commit into
fix/macos-keychain-promptsfrom
fix/cargo-credential-auth-scheme

Conversation

@cloudsmith-iduffy

Copy link
Copy Markdown
Contributor

Description

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Refactoring
  • Other (please describe)

Additional Notes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cloudsmith-iduffy
cloudsmith-iduffy requested a review from a team as a code owner August 25, 2026 19:05
@cloudsmith-iduffy
cloudsmith-iduffy merged commit 06313f2 into fix/macos-keychain-prompts Aug 26, 2026
37 checks passed
@cloudsmith-iduffy
cloudsmith-iduffy deleted the fix/cargo-credential-auth-scheme branch August 26, 2026 15:54
cloudsmith-iduffy added a commit that referenced this pull request Aug 26, 2026
…sions (#383)

* fix(no-ticket): stop recurring macOS keychain prompts and self-heal dead SSO sessions

The keyring library implements each keychain write as a delete
followed by a re-create. The re-created item has a fresh access
control list, so every "Always Allow" grant was lost on the next
token refresh and the keychain prompts returned forever.

- Add core/macos_keychain.py and update keychain items in place with
  SecItemUpdate, which keeps the access control list. Fall back to
  the normal keyring write when the item does not exist. Resolve the
  chainer backend to its first member before the update.
- Scope keyring service names by profile. Non-default profiles read
  the legacy unscoped entries as a fallback, so existing sessions
  stay valid and migrate to scoped entries on the next refresh. The
  default profile keeps the unscoped names.
- Clear a profile's SSO tokens when the server rejects the refresh
  (400/401/403/422), so the CLI returns to a clean logged-out state
  instead of retrying dead tokens every 30 minutes. Transient
  failures keep the throttled retry. Treat a refresh response
  without an access token as a failure, and skip the refresh when no
  refresh token is stored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: restore refresh token import in keyring provider

Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>

* fix: defer credential provider imports and fix logout test assertion

The credential provider chain imported all providers at module level,
which pulled requests and cloudsmith_api into every CLI invocation
through the keyring provider's SAML dependency. Defer that import to
CredentialProviderChain.__init__ so it only loads when the chain is
built.

Also fix a logout test assertion that dropped the profile=None keyword
argument the command actually passes.

* fix: keep the default profile's session on scoped-profile logout

Logout deleted the legacy unscoped entries together with the
profile's scoped entries. The unscoped entries hold the default
profile's session, so a scoped-profile logout ended both sessions.
Delete the legacy entries only when the profile has no scoped
entries, as the refresh-rejection path already does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor: move the SSO refresh helpers into core

The keyring provider imported refresh_access_token from cli.saml,
so core depended on cli at import time. Move refresh_access_token
and raise_for_api_error into core/sso.py. cli/saml.py re-exports
them for its existing callers.

The deferred provider import in chain.py stays. decorators.py
imports chain on every CLI start, so a module-level provider
import would load requests and cloudsmith_api at startup and fail
test_cli_import_does_not_load_heavy_modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: patch the provider's refresh binding, mock the keyring backend

test_returns_none_on_refresh_failure patched saml.refresh_access_token,
but the provider binds the function at module level, so the patch did
not intercept and the 401 path never ran. On macOS the test could reach
the real keychain. Patch keyring_provider.refresh_access_token, patch
delete_sso_tokens, and mock get_keyring for the whole file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: include auth scheme in Cargo credentials (#394)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants