Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: chat accepts AC device tokens from native OS

Fallback auth path: if Auth0 token fails, validate as device token
by checking handle exists via the handle API. Enables chat from
ac-native devices that use device-token API credentials.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+29 -1
+29 -1
session-server/chat-manager.mjs
··· 365 365 return; 366 366 } 367 367 368 - // Authorization 368 + // Authorization (Auth0 token or AC device token) 369 369 let authorized; 370 370 if (instance.authorizedConnections[id]?.token === msg.content.token) { 371 371 authorized = instance.authorizedConnections[id].user; ··· 373 373 } else { 374 374 console.log("💬 Authorizing..."); 375 375 authorized = await this.authorize(instance, msg.content.token); 376 + // Fallback: AC device token (from ac-native device-token API) 377 + if (!authorized && msg.content.handle && msg.content.token) { 378 + authorized = await this.authorizeDeviceToken(instance, msg.content.handle, msg.content.token); 379 + } 376 380 if (authorized) { 377 381 instance.authorizedConnections[id] = { 378 382 token: msg.content.token, ··· 596 600 this.broadcast(instance, this.pack("message:hearts", { for: forId, count })); 597 601 } catch (err) { 598 602 console.error("💬 Heart error:", err); 603 + } 604 + } 605 + 606 + async authorizeDeviceToken(instance, handle, token) { 607 + // AC device tokens are "hmac.timestamp" — validate by looking up the handle 608 + if (!token || !token.includes(".") || !handle) return undefined; 609 + try { 610 + let host = this.dev ? "https://localhost:8888" : 611 + (instance.config.name === "chat-sotce" ? "https://sotce.net" : "https://aesthetic.computer"); 612 + const options = {}; 613 + if (this.agent) options.agent = this.agent; 614 + // Verify handle exists via the handle API 615 + const res = await fetch(`${host}/.netlify/functions/handle?handle=${handle.replace("@", "")}`, options); 616 + if (res.status === 200) { 617 + const data = await res.json(); 618 + if (data.sub) { 619 + console.log("💬 Device token authorized for @" + handle); 620 + return { sub: data.sub }; 621 + } 622 + } 623 + return undefined; 624 + } catch (err) { 625 + console.error("💬 Device token auth error:", err); 626 + return undefined; 599 627 } 600 628 } 601 629