ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
16
fork

Configure Feed

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

fix(api): add proper oauth store interfaces

byarielm.fyi 505261d3 f11dbf27

verified
+22 -25
+4 -8
packages/api/src/infrastructure/oauth/OAuthClientFactory.ts
··· 36 36 try { 37 37 const client = new NodeOAuthClient({ 38 38 clientMetadata, 39 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 40 - stateStore: stateStore as any, 41 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 42 - sessionStore: sessionStore as any, 39 + stateStore, 40 + sessionStore, 43 41 }); 44 42 console.log("[oauth-client] Loopback client created successfully"); 45 43 return client; ··· 82 80 jwks_uri: config.jwksUri, 83 81 }, 84 82 keyset: [privateKey], 85 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 86 - stateStore: stateStore as any, 87 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 88 - sessionStore: sessionStore as any, 83 + stateStore, 84 + sessionStore, 89 85 }); 90 86 }
+10 -11
packages/api/src/infrastructure/oauth/stores/SessionStore.ts
··· 1 1 import { db } from "../../../db/client"; 2 - import { SessionData } from "../types"; 2 + import type { SimpleStore, GetOptions } from "@atproto-labs/simple-store"; 3 + import type { NodeSavedSession } from "@atproto/oauth-client-node"; 3 4 import { 4 5 encryptToken, 5 6 decryptToken, ··· 9 10 interface EncryptedSessionData { 10 11 encrypted: true; 11 12 dpopJwk: unknown; 12 - authMethod: string; 13 13 tokenSet: string; // Encrypted tokenSet 14 14 } 15 15 16 16 /** 17 17 * PostgreSQL-backed session store for OAuth sessions 18 18 * Encrypts token sets at rest for security 19 + * Implements SimpleStore<string, NodeSavedSession> for compatibility with @atproto/oauth-client-node 19 20 */ 20 - export class PostgresSessionStore { 21 + export class PostgresSessionStore implements SimpleStore<string, NodeSavedSession> { 21 22 private encryptionEnabled = isEncryptionConfigured(); 22 23 23 - async get(key: string): Promise<SessionData | undefined> { 24 + async get(key: string, _options?: GetOptions): Promise<NodeSavedSession | undefined> { 24 25 const result = await db 25 26 .selectFrom("oauth_sessions") 26 27 .select("session_data") ··· 42 43 try { 43 44 const encryptedData = stored as EncryptedSessionData; 44 45 // Decrypt tokenSet and reconstruct with dpopJwk 45 - const decryptedTokenSet = decryptToken<SessionData["tokenSet"]>( 46 + const decryptedTokenSet = decryptToken<NodeSavedSession["tokenSet"]>( 46 47 encryptedData.tokenSet, 47 48 ); 48 49 49 50 return { 50 51 dpopJwk: encryptedData.dpopJwk, 51 52 tokenSet: decryptedTokenSet, 52 - authMethod: encryptedData.authMethod, 53 - }; 53 + } as NodeSavedSession; 54 54 } catch (error) { 55 55 console.error( 56 56 "[SessionStore] Failed to decrypt session token set:", ··· 61 61 } 62 62 63 63 // Fallback for unencrypted format 64 - return stored as SessionData; 64 + return stored as NodeSavedSession; 65 65 } 66 66 67 - async set(key: string, value: SessionData): Promise<void> { 67 + async set(key: string, value: NodeSavedSession): Promise<void> { 68 68 let dataToStore: Record<string, unknown>; 69 69 70 70 if (this.encryptionEnabled) { 71 - // Encrypt only tokenSet, keep dpopJwk and authMethod as-is 71 + // Encrypt only tokenSet, keep dpopJwk as-is 72 72 dataToStore = { 73 73 encrypted: true, 74 74 dpopJwk: value.dpopJwk, 75 - authMethod: value.authMethod, 76 75 tokenSet: encryptToken(value.tokenSet), 77 76 }; 78 77 } else {
+8 -6
packages/api/src/infrastructure/oauth/stores/StateStore.ts
··· 1 1 import { db } from "../../../db/client"; 2 - import { StateData } from "../types"; 2 + import type { SimpleStore, GetOptions } from "@atproto-labs/simple-store"; 3 + import type { NodeSavedState } from "@atproto/oauth-client-node"; 3 4 4 5 /** 5 6 * PostgreSQL-backed state store for OAuth flow 6 7 * Stores ephemeral state data with automatic expiry (1 hour via cleanup job) 8 + * Implements SimpleStore<string, NodeSavedState> for compatibility with @atproto/oauth-client-node 7 9 */ 8 - export class PostgresStateStore { 9 - async get(key: string): Promise<StateData | undefined> { 10 + export class PostgresStateStore implements SimpleStore<string, NodeSavedState> { 11 + async get(key: string, _options?: GetOptions): Promise<NodeSavedState | undefined> { 10 12 const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000); 11 13 12 14 const result = await db ··· 18 20 19 21 if (!result) return undefined; 20 22 21 - // State data contains dpopKey which must remain as JWK object 22 - return result.data as unknown as StateData; 23 + // State data contains dpopJwk which must remain as JWK object 24 + return result.data as unknown as NodeSavedState; 23 25 } 24 26 25 - async set(key: string, value: StateData): Promise<void> { 27 + async set(key: string, value: NodeSavedState): Promise<void> { 26 28 try { 27 29 console.log("[StateStore] Storing state:", key); 28 30 await db