Skip to content

fix: add macOS Keychain fallback for Claude Code v2.1.63+ auth#14

Merged
JerrettDavis merged 2 commits intomainfrom
fix/macos-keychain-auth-fallback
Mar 2, 2026
Merged

fix: add macOS Keychain fallback for Claude Code v2.1.63+ auth#14
JerrettDavis merged 2 commits intomainfrom
fix/macos-keychain-auth-fallback

Conversation

@JerrettDavis
Copy link
Owner

Claude Code v2.1.63+ intentionally stores OAuth credentials in the macOS system Keychain (service 'Claude Code-credentials') and deletes ~/.claude/.credentials.json after migration. This caused the connector to report 'Not authenticated' on macOS even when claude login succeeded.

The provider now tries the credentials file first (Linux/Windows path), then falls back to reading from the macOS Keychain via the security CLI tool when the file is absent. Both the full credentials-file JSON format and the raw OAuth object format are handled.

A pluggable KeychainReader delegate (internal) allows unit tests to exercise the new code path without requiring a live macOS Keychain.

Fixes: JerrettDavis/JD.AI#6

Description

Related Issue

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Dependency update

Checklist

  • My code follows the project's coding standards (.editorconfig)
  • I have added/updated XML doc comments for public APIs
  • I have added tests that cover my changes
  • All new and existing tests pass (dotnet test)
  • The solution builds with zero warnings (dotnet build)
  • I have updated the documentation if needed
  • I have updated CHANGELOG.md (for user-facing changes)

Testing

Screenshots / Logs

Claude Code v2.1.63+ intentionally stores OAuth credentials in the
macOS system Keychain (service 'Claude Code-credentials') and deletes
~/.claude/.credentials.json after migration. This caused the connector
to report 'Not authenticated' on macOS even when claude login succeeded.

The provider now tries the credentials file first (Linux/Windows path),
then falls back to reading from the macOS Keychain via the `security`
CLI tool when the file is absent. Both the full credentials-file JSON
format and the raw OAuth object format are handled.

A pluggable `KeychainReader` delegate (internal) allows unit tests to
exercise the new code path without requiring a live macOS Keychain.

Fixes: JerrettDavis/JD.AI#6
@JerrettDavis JerrettDavis requested a review from Copilot March 2, 2026 17:26
@JerrettDavis JerrettDavis self-assigned this Mar 2, 2026
@github-actions
Copy link

github-actions bot commented Mar 2, 2026

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

Test Results

182 tests   173 ✅  3s ⏱️
  5 suites    9 💤
  5 files      0 ❌

Results for commit b30146b.

♻️ This comment has been updated with latest results.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a macOS fallback for Claude Code authentication by reading OAuth credentials from the system Keychain when the legacy ~/.claude/.credentials.json file is absent (as of Claude Code v2.1.63+ on macOS).

Changes:

  • Add macOS Keychain credential lookup (via security) as a fallback when the credentials file cannot be loaded.
  • Introduce an internal, pluggable KeychainReader delegate to enable deterministic unit testing.
  • Expand unit tests to cover Keychain wrapped/raw formats, invalid data, and precedence over the credentials file.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/JD.SemanticKernel.Connectors.ClaudeCode/ClaudeCodeSessionProvider.cs Adds macOS Keychain fallback logic and a default reader implementation using the security CLI.
tests/JD.SemanticKernel.Connectors.ClaudeCode.Tests/ClaudeCodeSessionProviderTests.cs Adds tests for Keychain fallback behavior and updates existing tests to disable Keychain reads when appropriate.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@JerrettDavis
Copy link
Owner Author

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link

Copilot AI commented Mar 2, 2026

@JerrettDavis I've opened a new pull request, #15, to work on those changes. Once the pull request is ready, I'll request review from you.

The macOS Keychain fallback was gated by OperatingSystem.IsMacOS()
which prevented the injected test KeychainReader from being called
on non-macOS CI runners. Track whether the reader was overridden
and skip the OS check when a test stub is injected.

Apply code review suggestions:
- Reword log message from 'Credentials file not found' to
  'Credentials unavailable from file' for accuracy
- Stop redirecting stderr to avoid potential buffer deadlock
- Wire cancellation token to process kill in NETSTANDARD2_0 branch
  so a Keychain permission prompt cannot hang the caller

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JerrettDavis JerrettDavis force-pushed the fix/macos-keychain-auth-fallback branch from f335a43 to b30146b Compare March 2, 2026 18:00
@github-actions
Copy link

github-actions bot commented Mar 2, 2026

Code Coverage

Summary
  Generated on: 03/02/2026 - 18:02:17
  Coverage date: 03/02/2026 - 18:02:06 - 03/02/2026 - 18:02:14
  Parser: MultiReport (9x Cobertura)
  Assemblies: 1
  Classes: 10
  Files: 9
  Line coverage: 83.8%
  Covered lines: 213
  Uncovered lines: 41
  Coverable lines: 254
  Total lines: 838
  Branch coverage: 82.2% (74 of 90)
  Covered branches: 74
  Total branches: 90
  Method coverage: 92.8% (39 of 42)
  Full method coverage: 83.3% (35 of 42)
  Covered methods: 39
  Fully covered methods: 35
  Total methods: 42

JD.SemanticKernel.Connectors.ClaudeCode                                  83.8%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeCredentialsFile       100%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeHttpClientFactory     100%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeOAuthCredentials      100%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeSessionException     33.3%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeSessionHttpHandler   95.2%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeSessionOptions        100%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeCodeSessionProvider      76.1%
  JD.SemanticKernel.Connectors.ClaudeCode.ClaudeModelDiscovery            100%
  JD.SemanticKernel.Connectors.ClaudeCode.KernelBuilderExtensions        93.7%
  JD.SemanticKernel.Connectors.ClaudeCode.ServiceCollectionExtensions     100%

@JerrettDavis JerrettDavis merged commit 6a1cf5d into main Mar 2, 2026
10 checks passed
@JerrettDavis JerrettDavis deleted the fix/macos-keychain-auth-fallback branch March 2, 2026 18:03
@codecov-commenter
Copy link

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants