This repository has no description
0

Configure Feed

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

fix

+214 -62
+12 -11
app/src/app/auth/callback/page.tsx
··· 5 5 import { getAccessToken } from '@/lib/bluesky-auth'; 6 6 import { getProfile } from '@/lib/bluesky-api'; 7 7 import { useAuth } from '@/lib/auth-context'; 8 + import { retrieveAuthData, clearAuthData } from '@/lib/storage-util'; 8 9 import styles from './callback.module.css'; 9 10 10 11 // Loading component to show while waiting ··· 49 50 return; 50 51 } 51 52 52 - // Get stored values from session storage 53 - if (typeof window === 'undefined' || !window.sessionStorage) { 54 - setError('Browser storage not available'); 53 + // Get stored values from our robust storage utility 54 + if (typeof window === 'undefined') { 55 + setError('Browser environment not available'); 55 56 return; 56 57 } 57 58 58 - const storedState = sessionStorage.getItem('oauth_state'); 59 - const codeVerifier = sessionStorage.getItem('code_verifier'); 60 - const serializedKeyPair = sessionStorage.getItem('key_pair'); 59 + const storedState = retrieveAuthData('oauth_state'); 60 + const codeVerifier = retrieveAuthData('code_verifier'); 61 + const serializedKeyPair = retrieveAuthData('key_pair'); 61 62 62 63 console.log('Callback received state:', state?.substring(0, 5) + '...'); 63 64 console.log('Stored state:', storedState?.substring(0, 5) + '...'); 64 65 65 66 // Check if we have the stored values 66 67 if (!storedState) { 67 - console.error('No stored OAuth state found. Session storage may have been cleared.'); 68 + console.error('No stored OAuth state found. Browser storage may have been cleared.'); 68 69 setError('Session data lost. Please try logging in again.'); 69 70 return; 70 71 } ··· 229 230 pdsEndpoint: pdsEndpoint // Store the PDS endpoint for later use 230 231 }); 231 232 232 - // Clear session storage 233 - sessionStorage.removeItem('oauth_state'); 234 - sessionStorage.removeItem('code_verifier'); 235 - sessionStorage.removeItem('key_pair'); 233 + // Clear storage 234 + clearAuthData('oauth_state'); 235 + clearAuthData('code_verifier'); 236 + clearAuthData('key_pair'); 236 237 237 238 // Redirect to dashboard 238 239 router.push('/dashboard');
+10 -19
app/src/app/auth/login/page.tsx
··· 3 3 import { useEffect, useState } from 'react'; 4 4 import { useRouter } from 'next/navigation'; 5 5 import { getAuthorizationUrl } from '@/lib/bluesky-auth'; 6 + import { storeAuthData } from '@/lib/storage-util'; 6 7 import styles from './login.module.css'; 7 8 8 9 export default function LoginPage() { ··· 35 36 // Get authorization URL 36 37 const { url, state, codeVerifier, keyPair } = await getAuthorizationUrl(); 37 38 38 - // Store auth state in sessionStorage 39 + // Store auth state in both storage mechanisms 39 40 try { 40 - // Clear any old values first 41 - sessionStorage.removeItem('oauth_state'); 42 - sessionStorage.removeItem('code_verifier'); 43 - sessionStorage.removeItem('key_pair'); 44 - 45 - // Set new values 46 - sessionStorage.setItem('oauth_state', state); 47 - sessionStorage.setItem('code_verifier', codeVerifier); 48 - 49 - // Serialize and store keyPair 41 + // Serialize the key pair 50 42 const publicJwk = await window.crypto.subtle.exportKey('jwk', keyPair.publicKey); 51 43 const privateJwk = await window.crypto.subtle.exportKey('jwk', keyPair.privateKey); 52 44 const serializedKeyPair = JSON.stringify({ publicKey: publicJwk, privateKey: privateJwk }); 53 - sessionStorage.setItem('key_pair', serializedKeyPair); 54 45 55 - // Double-check that values were stored correctly 56 - const storedState = sessionStorage.getItem('oauth_state'); 57 - const storedVerifier = sessionStorage.getItem('code_verifier'); 58 - const storedKeyPair = sessionStorage.getItem('key_pair'); 46 + // Store all values with our utility functions 47 + const stateStored = storeAuthData('oauth_state', state); 48 + const verifierStored = storeAuthData('code_verifier', codeVerifier); 49 + const keyPairStored = storeAuthData('key_pair', serializedKeyPair); 59 50 60 - if (!storedState || !storedVerifier || !storedKeyPair) { 61 - throw new Error('Failed to store authentication data'); 51 + if (!stateStored || !verifierStored || !keyPairStored) { 52 + throw new Error('Failed to store one or more authentication values'); 62 53 } 63 54 64 - console.log('OAuth state stored successfully:', state.substring(0, 5) + '...'); 55 + console.log('OAuth data stored successfully:', state.substring(0, 5) + '...'); 65 56 } catch (storageError) { 66 57 console.error('Error storing OAuth state:', storageError); 67 58 setError('Failed to store login state. Please ensure cookies and storage are enabled.');
+9 -3
app/src/lib/bluesky-api.ts
··· 51 51 publicKey, 52 52 'GET', 53 53 url, 54 - dpopNonce || undefined 54 + dpopNonce || undefined, 55 + accessToken // Pass the access token for ath claim 55 56 ); 56 57 57 58 console.log('Making auth check request to:', url); ··· 232 233 const baseUrl = pdsEndpoint ? `${pdsEndpoint}/xrpc` : 'https://bsky.social/xrpc'; 233 234 // Include the handle parameter in the URL for token creation 234 235 const endpoint = `${baseUrl}/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`; 236 + 237 + // Generate the DPoP token with the access token for the ath claim 235 238 const dpopToken = await generateDPoPToken( 236 239 keyPair.privateKey, 237 240 publicKey, 238 241 'GET', 239 242 endpoint, 240 - dpopNonce || undefined 243 + dpopNonce || undefined, 244 + accessToken // Include access token for ath claim 241 245 ); 242 246 243 247 // Make the request via our proxy API ··· 312 316 const publicKey = await exportJWK(keyPair.publicKey); 313 317 314 318 console.log('Generating DPoP token for:', endpoint, 'with nonce:', dpopNonce || 'none'); 319 + console.log('Including access token hash (ath) in DPoP token'); 315 320 316 321 const dpopToken = await generateDPoPToken( 317 322 keyPair.privateKey, 318 323 publicKey, 319 324 'POST', 320 325 endpoint, 321 - dpopNonce || undefined 326 + dpopNonce || undefined, 327 + accessToken // Pass the access token for ath claim 322 328 ); 323 329 324 330 // Make the request via our proxy API
+32 -2
app/src/lib/bluesky-auth.ts
··· 53 53 return await window.crypto.subtle.exportKey('jwk', key); 54 54 } 55 55 56 + // Calculate the SHA-256 hash of a string 57 + async function sha256(str: string): Promise<ArrayBuffer> { 58 + const encoder = new TextEncoder(); 59 + const data = encoder.encode(str); 60 + return await window.crypto.subtle.digest('SHA-256', data); 61 + } 62 + 63 + // Convert ArrayBuffer to base64url string 64 + function arrayBufferToBase64Url(buffer: ArrayBuffer): string { 65 + const bytes = new Uint8Array(buffer); 66 + let binary = ''; 67 + for (let i = 0; i < bytes.byteLength; i++) { 68 + binary += String.fromCharCode(bytes[i]); 69 + } 70 + return btoa(binary) 71 + .replace(/\+/g, '-') 72 + .replace(/\//g, '_') 73 + .replace(/=+$/, ''); 74 + } 75 + 56 76 // Generate a DPoP token 57 77 export async function generateDPoPToken( 58 78 privateKey: CryptoKey, 59 79 publicKey: JsonWebKey, 60 80 method: string, 61 81 url: string, 62 - nonce?: string 82 + nonce?: string, 83 + accessToken?: string // Add optional access token for ath claim 63 84 ): Promise<string> { 64 85 const now = Math.floor(Date.now() / 1000); 65 86 const jti = generateRandomString(16); ··· 77 98 iat: now 78 99 }; 79 100 101 + // Add nonce if provided 80 102 if (nonce) { 81 103 payload.nonce = nonce; 104 + } 105 + 106 + // Add access token hash (ath) if access token is provided 107 + if (accessToken) { 108 + console.log('Adding ath claim to DPoP token'); 109 + const tokenHash = await sha256(accessToken); 110 + payload.ath = arrayBufferToBase64Url(tokenHash); 82 111 } 83 112 84 113 const encodedHeader = btoa(JSON.stringify(header)) ··· 237 266 238 267 console.log('Creating DPoP token with nonce:', dpopNonce); 239 268 240 - // Create DPoP token with nonce if we have one 269 + // For token requests, we don't include the ath claim as we don't have the token yet 241 270 const publicKey = await exportJWK(keyPair.publicKey); 242 271 const dpopToken = await generateDPoPToken( 243 272 keyPair.privateKey, ··· 245 274 'POST', 246 275 tokenEndpoint, 247 276 dpopNonce 277 + // No access token for token requests as we don't have it yet 248 278 ); 249 279 250 280 console.log('Making token request via proxy API');
+59
app/src/lib/storage-util.ts
··· 1 + // A utility file to handle browser storage robustly 2 + 3 + // Store data with both localStorage and sessionStorage for redundancy 4 + export function storeAuthData(key: string, value: string): boolean { 5 + try { 6 + // Clear any existing values first 7 + sessionStorage.removeItem(key); 8 + localStorage.removeItem(key); 9 + 10 + // Store in both storages for redundancy 11 + sessionStorage.setItem(key, value); 12 + localStorage.setItem(`bsky_auth_${key}`, value); // Use a prefix to avoid conflicts 13 + 14 + return true; 15 + } catch (error) { 16 + console.error(`Failed to store auth data for key ${key}:`, error); 17 + return false; 18 + } 19 + } 20 + 21 + // Retrieve data from sessionStorage first, fall back to localStorage 22 + export function retrieveAuthData(key: string): string | null { 23 + try { 24 + // Try sessionStorage first (preferred) 25 + const sessionValue = sessionStorage.getItem(key); 26 + if (sessionValue) { 27 + return sessionValue; 28 + } 29 + 30 + // Fall back to localStorage if needed 31 + const localValue = localStorage.getItem(`bsky_auth_${key}`); 32 + if (localValue) { 33 + console.log(`Retrieved auth data for ${key} from localStorage fallback`); 34 + // Store it back in sessionStorage for next time 35 + try { 36 + sessionStorage.setItem(key, localValue); 37 + } catch (e) { 38 + console.warn('Could not restore value to sessionStorage:', e); 39 + } 40 + return localValue; 41 + } 42 + 43 + // Nothing found 44 + return null; 45 + } catch (error) { 46 + console.error(`Failed to retrieve auth data for key ${key}:`, error); 47 + return null; 48 + } 49 + } 50 + 51 + // Clear auth data from both storages 52 + export function clearAuthData(key: string): void { 53 + try { 54 + sessionStorage.removeItem(key); 55 + localStorage.removeItem(`bsky_auth_${key}`); 56 + } catch (error) { 57 + console.error(`Failed to clear auth data for key ${key}:`, error); 58 + } 59 + }
+69 -27
contextual info for claude/app_errors.md
··· 1 1 Storage access automatically granted for Dynamic State Partitioning “https://bsky.social” on “https://flushing.im”. callback 2 2 GET 3 3 https://flushing.im/favicon.ico 4 - [HTTP/2 404 58ms] 4 + [HTTP/2 404 61ms] 5 5 6 - Exchanging code for token... page-ae3301580eb0dbbc.js:1:1598 7 - No nonce provided, getting one from API... 481-5b7d3c6f8bc564a2.js:1:8088 8 - Obtained nonce from API: Dq3xrB2CbvGOdqtF5avAauCvScf1FYV_QDmpQ8wZqG4 481-5b7d3c6f8bc564a2.js:1:8165 9 - Creating DPoP token with nonce: Dq3xrB2CbvGOdqtF5avAauCvScf1FYV_QDmpQ8wZqG4 481-5b7d3c6f8bc564a2.js:1:8277 10 - Making token request via proxy API 481-5b7d3c6f8bc564a2.js:1:8416 11 - Token request successful 481-5b7d3c6f8bc564a2.js:1:8909 12 - Token audience: undefined page-ae3301580eb0dbbc.js:1:1950 13 - Token audience missing or not a string: undefined page-ae3301580eb0dbbc.js:1:2208 14 - Getting profile via proxy API 481-5b7d3c6f8bc564a2.js:1:3263 6 + Callback received state: 9StyI... page-099e80a200860a21.js:1:1095 7 + Stored state: 9StyI... page-099e80a200860a21.js:1:1175 8 + Exchanging code for token... page-099e80a200860a21.js:1:2016 9 + No nonce provided, getting one from API... 481-d3c58c35fd99af50.js:1:8385 10 + Obtained nonce from API: nnKOYi3GWF5VHcaGl3ZfUAQeplTiEeWEi6_FH2BGrLI 481-d3c58c35fd99af50.js:1:8462 11 + Creating DPoP token with nonce: nnKOYi3GWF5VHcaGl3ZfUAQeplTiEeWEi6_FH2BGrLI 481-d3c58c35fd99af50.js:1:8574 12 + Making token request via proxy API 481-d3c58c35fd99af50.js:1:8713 13 + Token request successful 481-d3c58c35fd99af50.js:1:9206 14 + Token audience: undefined page-099e80a200860a21.js:1:2368 15 + Token audience missing or not a string: undefined page-099e80a200860a21.js:1:2626 16 + Getting profile via proxy API 481-d3c58c35fd99af50.js:1:3560 15 17 Token response: 16 - Object { access_token: "eyJ0eXAiOiJhdCtqd3QiLCJhbGciOiJFUzI1NksifQ.eyJhdWQiOiJkaWQ6d2ViOmVub2tpLnVzLWVhc3QuaG9zdC5ic2t5Lm5ldHdvcmsiLCJpYXQiOjE3NDEzODk4NjEsImV4cCI6MTc0MTM5MzQ2MSwic3ViIjoiZGlkOnBsYzpncTRmbzN1NnRxenpka2psd3pwYjIzdGoiLCJqdGkiOiJ0b2stYTRkNzdkNmZkZmExMmUwODkzNWJjNTQwYTJjMDBkNTEiLCJjbmYiOnsiamt0IjoieVlqUjRmb0JVSXY0RzZCX21Kb29abmR5ZFBHcmtwZEpBeXVpTDk0RGl6VSJ9LCJjbGllbnRfaWQiOiJodHRwczovL2ZsdXNoaW5nLmltL2NsaWVudC1tZXRhZGF0YS5qc29uIiwic2NvcGUiOiJhdHByb3RvIHRyYW5zaXRpb246Z2VuZXJpYyIsImlzcyI6Imh0dHBzOi8vYnNreS5zb2NpYWwifQ.gtS_fu7hSVR6DLgC-DD4yKGianrn6mBhSAwN14_TytGm2QMwbHXbGYDzV3c0cOCZ_Kw5SmJLUUZDp-y4gWwLXA", token_type: "DPoP", refresh_token: "ref-315fa3def8f4c3a0faa828188205642b078d126c8a22f5a4b68d262e6aceba1f", scope: "atproto transition:generic", expires_in: 3599, sub: "did:plc:gq4fo3u6tqzzdkjlwzpb23tj" } 17 - page-ae3301580eb0dbbc.js:1:2465 18 - User DID from token: did:plc:gq4fo3u6tqzzdkjlwzpb23tj page-ae3301580eb0dbbc.js:1:2510 18 + Object { access_token: "eyJ0eXAiOiJhdCtqd3QiLCJhbGciOiJFUzI1NksifQ.eyJhdWQiOiJkaWQ6d2ViOmVub2tpLnVzLWVhc3QuaG9zdC5ic2t5Lm5ldHdvcmsiLCJpYXQiOjE3NDEzOTAzMzcsImV4cCI6MTc0MTM5MzkzNywic3ViIjoiZGlkOnBsYzpncTRmbzN1NnRxenpka2psd3pwYjIzdGoiLCJqdGkiOiJ0b2stODAwZjEwZTEzOTEyYjA0MTljOGYyZTc4ZDkzZWRkZjIiLCJjbmYiOnsiamt0IjoiR3lXWnA3cUZOajFiaWttMHhRX1pMTGR4WnhMVTdCNmRqaEZSTU1HR1o0TSJ9LCJjbGllbnRfaWQiOiJodHRwczovL2ZsdXNoaW5nLmltL2NsaWVudC1tZXRhZGF0YS5qc29uIiwic2NvcGUiOiJhdHByb3RvIHRyYW5zaXRpb246Z2VuZXJpYyIsImlzcyI6Imh0dHBzOi8vYnNreS5zb2NpYWwifQ.fIVsf2SJRsaPDCRpaJhYyFsXOpGcvxxutZhqHfLwS97XtMxh63yPZZq26vhC2aHJ_7omR1a6MJjEptDZfvTrVQ", token_type: "DPoP", refresh_token: "ref-2dda4b2d21fbb21df5b02d34f3dafd35ccef542b4a4fce652b3ce1958c7571cd", scope: "atproto transition:generic", expires_in: 3599, sub: "did:plc:gq4fo3u6tqzzdkjlwzpb23tj" } 19 + page-099e80a200860a21.js:1:2883 20 + User DID from token: did:plc:gq4fo3u6tqzzdkjlwzpb23tj page-099e80a200860a21.js:1:2928 19 21 Decoded token payload: 20 - Object { aud: "did:web:enoki.us-east.host.bsky.network", iat: 1741389861, exp: 1741393461, sub: "did:plc:gq4fo3u6tqzzdkjlwzpb23tj", jti: "tok-a4d77d6fdfa12e08935bc540a2c00d51", cnf: {…}, client_id: "https://flushing.im/client-metadata.json", scope: "atproto transition:generic", iss: "https://bsky.social" } 21 - page-ae3301580eb0dbbc.js:1:2649 22 - Audience from decoded token: did:web:enoki.us-east.host.bsky.network page-ae3301580eb0dbbc.js:1:2721 23 - Updated PDS endpoint from decoded token: https://enoki.us-east.host.bsky.network page-ae3301580eb0dbbc.js:1:2844 24 - Using PDS endpoint for API requests: https://enoki.us-east.host.bsky.network page-ae3301580eb0dbbc.js:1:3000 25 - Submitting status update with DID: did:plc:gq4fo3u6tqzzdkjlwzpb23tj page-d2f66577bcd815c7.js:1:1200 26 - Using PDS endpoint: https://enoki.us-east.host.bsky.network page-d2f66577bcd815c7.js:1:1252 27 - Checking auth with PDS endpoint: https://enoki.us-east.host.bsky.network 481-5b7d3c6f8bc564a2.js:1:2403 28 - XHRGET 29 - https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.listRecords?limit=1 30 - [HTTP/2 400 29ms] 22 + Object { aud: "did:web:enoki.us-east.host.bsky.network", iat: 1741390337, exp: 1741393937, sub: "did:plc:gq4fo3u6tqzzdkjlwzpb23tj", jti: "tok-800f10e13912b0419c8f2e78d93eddf2", cnf: {…}, client_id: "https://flushing.im/client-metadata.json", scope: "atproto transition:generic", iss: "https://bsky.social" } 23 + page-099e80a200860a21.js:1:3078 24 + Audience from decoded token: did:web:enoki.us-east.host.bsky.network page-099e80a200860a21.js:1:3150 25 + Extracted PDS endpoint from decoded token: https://enoki.us-east.host.bsky.network page-099e80a200860a21.js:1:3273 26 + Using PDS endpoint for API requests: https://enoki.us-east.host.bsky.network page-099e80a200860a21.js:1:3533 27 + Saving PDS endpoint to auth context: https://enoki.us-east.host.bsky.network page-099e80a200860a21.js:1:3587 28 + Callback received state: 9StyI... page-099e80a200860a21.js:1:1095 29 + Stored state: undefined... page-099e80a200860a21.js:1:1175 30 + No stored OAuth state found. Session storage may have been cleared. 117-89c59c874aec3528.js:1:4081 31 + Submitting status update with DID: did:plc:gq4fo3u6tqzzdkjlwzpb23tj page-1f5ea258c75e5bac.js:1:1200 32 + Using PDS endpoint: https://enoki.us-east.host.bsky.network page-1f5ea258c75e5bac.js:1:1252 33 + Checking auth with PDS endpoint: https://enoki.us-east.host.bsky.network 481-d3c58c35fd99af50.js:1:2469 34 + Making auth check request to: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.identity.resolveHandle?handle=atproto.com 481-d3c58c35fd99af50.js:1:2709 35 + Auth check successful! 481-d3c58c35fd99af50.js:1:2856 36 + Authentication verified, creating status... page-1f5ea258c75e5bac.js:1:1662 37 + Creating flushing status (attempt 1/3) with nonce: null 481-d3c58c35fd99af50.js:1:4526 38 + Using PDS endpoint: https://enoki.us-east.host.bsky.network 481-d3c58c35fd99af50.js:1:4608 39 + API endpoint: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.createRecord 481-d3c58c35fd99af50.js:1:4985 40 + Generating DPoP token for: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.createRecord with nonce: none 481-d3c58c35fd99af50.js:1:5050 41 + Sending request to proxy API... 481-d3c58c35fd99af50.js:1:5174 42 + XHRPOST 43 + https://flushing.im/api/bluesky/flushing 44 + [HTTP/2 401 200ms] 31 45 32 - Auth check failed with status: 400 117-6f305e70e5d65397.js:1:4081 33 - NextJS 32 46 + Status creation error: 47 + Object { error: "use_dpop_nonce", nonce: "Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA", originalError: {…} } 48 + 117-89c59c874aec3528.js:1:4081 49 + Received DPoP nonce error, retrying with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:5620 50 + Creating flushing status (attempt 2/3) with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:4526 51 + Using PDS endpoint: https://enoki.us-east.host.bsky.network 481-d3c58c35fd99af50.js:1:4608 52 + API endpoint: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.createRecord 481-d3c58c35fd99af50.js:1:4985 53 + Generating DPoP token for: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.createRecord with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:5050 54 + Sending request to proxy API... 481-d3c58c35fd99af50.js:1:5174 55 + XHRPOST 56 + https://flushing.im/api/bluesky/flushing 57 + [HTTP/2 401 63ms] 34 58 59 + Status creation error: 60 + Object { error: "use_dpop_nonce", nonce: "Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA", originalError: {…} } 61 + 117-89c59c874aec3528.js:1:4081 62 + Received DPoP nonce error, retrying with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:5620 63 + Creating flushing status (attempt 3/3) with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:4526 64 + Using PDS endpoint: https://enoki.us-east.host.bsky.network 481-d3c58c35fd99af50.js:1:4608 65 + API endpoint: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.createRecord 481-d3c58c35fd99af50.js:1:4985 66 + Generating DPoP token for: https://enoki.us-east.host.bsky.network/xrpc/com.atproto.repo.createRecord with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:5050 67 + Sending request to proxy API... 481-d3c58c35fd99af50.js:1:5174 68 + XHRPOST 69 + https://flushing.im/api/bluesky/flushing 70 + [HTTP/2 401 102ms] 35 71 36 - Authentication check failed. Your login may have expired. 72 + Status creation error: 73 + Object { error: "use_dpop_nonce", nonce: "Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA", originalError: {…} } 74 + 117-89c59c874aec3528.js:1:4081 75 + Received DPoP nonce error, retrying with nonce: Cu3Gn9OQuKUyKfqV9bGK0pqqeHPvm-tWhsvc9-6cmkA 481-d3c58c35fd99af50.js:1:5620 76 + Failed to update status: Error: Maximum retry attempts reached. Could not create status after 3 attempts. 77 + NextJS 34 78 + 117-89c59c874aec3528.js:1:4081
+23
contextual info for claude/vercel_logs.md
··· 1 + API received pdsEndpoint: https://enoki.us-east.host.bsky.network 2 + Using API URL: https://enoki.us-east.host.bsky.network/xrpc 3 + Creating record with body: {"repo":"did:plc:gq4fo3u6tqzzdkjlwzpb23tj","collection":"im.flushing.right.now","record":{"$type":"im.flushing.right.now","text":"test","emoji":"🚽","createdAt":"2025-03-07T23:36:45.017Z"}} 4 + Request headers: {"Content-Type":"application/json","Authorization":"DPoP eyJ0eXAiOi...","DPoP":"eyJhbGciOi..."} 5 + Response headers: {"access-control-allow-origin":"*","access-control-expose-headers":"DPoP-Nonce, WWW-Authenticate","cache-control":"private","content-length":"60","content-type":"application/json; charset=utf-8","date":"Fri, 07 Mar 2025 23:36:45 GMT","dpop-nonce":"LlWfyMv8IBRNbacCkKvqPcPMHsLtVcQmr8pYXCISA8c","etag":"W/\"3c-fFVTtGbi81z3YpltLLm+eGgcNto\"","keep-alive":"timeout=90","strict-transport-security":"max-age=63072000","vary":"Authorization, Accept-Encoding","www-authenticate":"DPoP algs=\"RS256 RS384 RS512 PS256 PS384 PS512 ES256 ES256K ES384 ES512\", error=\"invalid_dpop_proof\", error_description=\"DPoP ath mismatch\"","x-powered-by":"Express"} 6 + Create record response status: 401 7 + Create record response: {"error":"invalid_dpop_proof","message":"DPoP ath mismatch"} 8 + Received new DPoP nonce from PDS: LlWfyMv8IBRNbacCkKvqPcPMHsLtVcQmr8pYXCISA8c 9 + 10 + 11 + 12 + 1. No, I'm not using a private browsing window and I tried across other 13 + browsers and see the same result. 14 + 15 + 2. No CORS errors, but this is the originalError: 16 + { 17 + "originalError": { 18 + "error": "use_dpop_nonce", 19 + "message": "Authorization server requires nonce in DPoP proof" 20 + } 21 + } 22 + 23 + 3. I added a new file at "contextual info for claude/vercel_logs.md" where you can see the vercel logs. The hotsname of my deployed site is indeed flushing.im