diff --git a/ClaudeChecker/Info.plist b/ClaudeChecker/Info.plist
index 5ae3940..9d6db50 100644
--- a/ClaudeChecker/Info.plist
+++ b/ClaudeChecker/Info.plist
@@ -15,9 +15,9 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.2.1-beta.7
+ 1.2.1-beta.8
CFBundleVersion
- 55
+ 56
LSMinimumSystemVersion
13.0
LSUIElement
diff --git a/ClaudeChecker/LoginView.swift b/ClaudeChecker/LoginView.swift
index 26830cb..4176f4e 100644
--- a/ClaudeChecker/LoginView.swift
+++ b/ClaudeChecker/LoginView.swift
@@ -36,13 +36,19 @@ struct LoginWebView: NSViewRepresentable {
if let url = webView.url?.absoluteString,
url.contains("/login") || url.contains("/auth") { return }
- // URL is not a login/auth page, so if any claude.ai cookie exists we're signed in
- WKWebsiteDataStore.default().httpCookieStore.getAllCookies { cookies in
- let hasAnyCookie = cookies.contains { $0.domain.contains("claude.ai") || $0.domain.contains("anthropic.com") }
- guard hasAnyCookie, !self.didAuthenticate else { return }
- self.didAuthenticate = true
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
- self.onAuthenticated()
+ // Ask the WebView itself whether we're authenticated — it uses its own
+ // session (cookies, localStorage, etc.) so we don't need to know the
+ // cookie domain or name.
+ webView.callAsyncJavaScript(
+ "const r = await fetch('/api/bootstrap', {credentials: 'include'}); return r.status;",
+ arguments: [:], in: nil, in: .defaultClient
+ ) { [weak self] result in
+ guard let self, !self.didAuthenticate else { return }
+ if case .success(let val) = result, let status = val as? Int, status == 200 {
+ self.didAuthenticate = true
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+ self.onAuthenticated()
+ }
}
}
}
diff --git a/ClaudeChecker/UsageViewModel.swift b/ClaudeChecker/UsageViewModel.swift
index b96caf6..9ab091d 100644
--- a/ClaudeChecker/UsageViewModel.swift
+++ b/ClaudeChecker/UsageViewModel.swift
@@ -43,8 +43,7 @@ class UsageViewModel: ObservableObject {
private func checkInitialSignInState() async {
let cookies = await WKWebsiteDataStore.default().httpCookieStore.allCookies()
- let hasAnyCookie = cookies.contains { $0.domain.contains("claude.ai") || $0.domain.contains("anthropic.com") }
- if hasAnyCookie { isSignedIn = true }
+ if !cookies.isEmpty { isSignedIn = true }
}
func signOut() async {
@@ -193,8 +192,10 @@ class UsageViewModel: ObservableObject {
private func claudeCookieHeader() async -> String? {
let cookies = await WKWebsiteDataStore.default().httpCookieStore.allCookies()
- let claudeCookies = cookies.filter { $0.domain.contains("claude.ai") || $0.domain.contains("anthropic.com") }
- return HTTPCookie.requestHeaderFields(with: claudeCookies)["Cookie"]
+ guard !cookies.isEmpty else { return nil }
+ // Send all cookies from the app's WebView store — the session token may be
+ // on any domain (claude.ai, anthropic.com, or an auth sub-service).
+ return HTTPCookie.requestHeaderFields(with: cookies)["Cookie"]
}
private func fetchUsage(orgId: String) async throws -> UsageResponse {
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index d3c4a36..4d7fbbf 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -7,5 +7,6 @@
- Fixed "No API key configured" showing after signing out — now correctly shows "Not signed in" with a prompt to sign in
- Added `/api/organizations` as a final fallback for org ID resolution when the bootstrap API response doesn't include it
- Fixed usage data not loading — API requests now include required browser-like headers (Origin, Referer, User-Agent)
-- Fixed sign-in detection and cookie handling for accounts whose session cookies are on the `anthropic.com` domain rather than `claude.ai`
- Fixed Settings incorrectly showing "Signed in" after a failed refresh — sign-in state now resets when authentication fails
+- Rewrote login detection to use the WebView's own fetch call instead of inspecting cookie domains — correctly detects auth regardless of which domain the session token is stored on
+- Fixed API requests not including session cookies — now sends all cookies from the app's WebView store rather than filtering by domain