Skip to content

Commit ecc682c

Browse files
leogdionclaude
andcommitted
feat: enhance CloudKit.js web auth token extraction and update testing status
MAJOR IMPROVEMENTS: - Enhanced postMessage listener with origin verification (icloud.com, apple-cloudkit.com) - Added network request interception (fetch/XHR) as fallback token capture method - Extended timeout from 5s to 10s for token arrival - Added browser debugging helpers (mistKitDebug.*) - Simplified handleAuthentication() removing 160+ lines of non-working detection code IMPLEMENTATION DETAILS: Phase 1: Enhanced postMessage capture - Origin validation for security - Support for multiple token formats (plain string `158__54__...`, object properties) - Global token storage in window.cloudKitWebAuthToken Phase 2: Network interception fallback - Intercepts fetch() and XMLHttpRequest - Captures tokens from CloudKit API responses - Logs all CloudKit requests for debugging Phase 3: Simplified authentication flow - Removed localStorage, cookies, property access strategies (didn't work) - Clean token promise with 10s timeout - Manual extraction instructions on failure Phase 5: Debugging helpers - mistKitDebug.container() - Get CloudKit container - mistKitDebug.token() - Get current token - mistKitDebug.setToken(tok) - Manually set token - mistKitDebug.sendToServer() - Send token to server - mistKitDebug.inspectContainer() - Inspect container for token TESTING STATUS UPDATE: - Web auth token successfully extracted manually (158__54__... format verified) - Implementation complete and ready for testing - Blocked on CloudKit container configuration (421 Misdirected Request) - Need to verify container setup at icloud.developer.apple.com/dashboard FILES MODIFIED: - Examples/MistDemo/Sources/MistDemo/Resources/index.html - Examples/MistDemo/Sources/MistDemo/MistDemo.swift - Examples/MistDemo/TESTING_STATUS.md Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 5b5b639 commit ecc682c

4 files changed

Lines changed: 531 additions & 255 deletions

File tree

Examples/MistDemo/Sources/MistDemo/MistDemo.swift

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,31 @@ func startWebAuthenticationServer(
190190
port: Int
191191
) async throws {
192192
let router = Router()
193-
194-
// Serve the CloudKit sign-in page
195-
router.get("/") { _, _ in
196-
let html = createCloudKitAuthHTML(
197-
apiToken: apiToken,
198-
containerIdentifier: containerIdentifier,
199-
environment: environment
200-
)
201-
var response = Response(status: .ok, body: .init(byteBuffer: ByteBuffer(string: html)))
202-
response.headers[.contentType] = "text/html"
203-
return response
193+
194+
// Serve static files from Resources directory (includes enhanced index.html)
195+
let possiblePaths = [
196+
Bundle.main.resourcePath ?? "",
197+
Bundle.main.bundlePath + "/Contents/Resources",
198+
"./Sources/MistDemo/Resources",
199+
"./Examples/MistDemo/Sources/MistDemo/Resources",
200+
URL(fileURLWithPath: #file).deletingLastPathComponent().appendingPathComponent("Resources").path
201+
]
202+
203+
var resourcesPath = "./Sources/MistDemo/Resources" // default fallback
204+
for path in possiblePaths {
205+
if !path.isEmpty && FileManager.default.fileExists(atPath: path + "/index.html") {
206+
resourcesPath = path
207+
print("📁 Serving static files from: \(resourcesPath)")
208+
break
209+
}
204210
}
211+
212+
router.middlewares.add(
213+
FileMiddleware(
214+
resourcesPath,
215+
searchForIndexHtml: true
216+
)
217+
)
205218

206219
// Handle the authentication callback
207220
router.post("/auth/callback") { request, context in
@@ -400,53 +413,39 @@ func createCloudKitAuthHTML(
400413
401414
async function sendTokenToServer(container) {
402415
try {
403-
console.log('Container object:', container);
404-
console.log('Available properties:', Object.keys(container));
405-
406-
// Try multiple ways to get the web auth token
407-
let webAuthToken = null;
408-
409-
// Method 1: session property
410-
if (container.session && container.session.webAuthToken) {
411-
webAuthToken = container.session.webAuthToken;
412-
console.log('Found token in session.webAuthToken');
413-
}
414-
// Method 2: direct property
415-
else if (container.webAuthToken) {
416-
webAuthToken = container.webAuthToken;
417-
console.log('Found token in container.webAuthToken');
418-
}
419-
// Method 3: auth property
420-
else if (container.auth && container.auth.webAuthToken) {
421-
webAuthToken = container.auth.webAuthToken;
422-
console.log('Found token in auth.webAuthToken');
423-
}
424-
// Method 4: _auth property (internal)
425-
else if (container._auth && container._auth.webAuthToken) {
426-
webAuthToken = container._auth.webAuthToken;
427-
console.log('Found token in _auth.webAuthToken');
428-
}
429-
430-
if (!webAuthToken) {
431-
console.error('No web auth token found. Container structure:', container);
432-
throw new Error('No web auth token available');
416+
// Token should be captured via postMessage/network interception
417+
const token = window.cloudKitWebAuthToken || container._auth?._ckSession;
418+
419+
if (!token) {
420+
console.error('No web auth token available');
421+
console.log('Container:', container);
422+
console.log('Try waiting a moment and checking window.cloudKitWebAuthToken');
423+
424+
// Wait 2 more seconds in case token is still arriving
425+
await new Promise(resolve => setTimeout(resolve, 2000));
426+
const retryToken = window.cloudKitWebAuthToken || container._auth?._ckSession;
427+
428+
if (!retryToken) {
429+
throw new Error('No web auth token available after retry');
430+
}
431+
432+
setStatus('Token found after retry, sending to server...', false);
433+
return sendTokenToServer(container); // Retry
433434
}
434-
435+
435436
const userInfo = container.userIdentity;
436-
console.log('Sending web auth token to server...', webAuthToken.substring(0, 20) + '...');
437-
438-
// Send to server
437+
console.log('Sending token to server...');
438+
console.log('Token preview:', token.substring(0, 30) + '...');
439+
439440
const response = await fetch('/auth/callback', {
440441
method: 'POST',
441-
headers: {
442-
'Content-Type': 'application/json',
443-
},
442+
headers: { 'Content-Type': 'application/json' },
444443
body: JSON.stringify({
445-
webAuthToken: webAuthToken,
444+
webAuthToken: token,
446445
userInfo: userInfo
447446
})
448447
});
449-
448+
450449
if (response.ok) {
451450
const html = await response.text();
452451
document.body.innerHTML = html;

0 commit comments

Comments
 (0)