Skip to content

Commit 7838f7d

Browse files
dylanjeffersclaude
andcommitted
fix(identity): correct audiusSdk accessor in authMiddleware (.full.users -> .users)
authMiddleware backfills blockchainUserId/handle for users whose identity row lacks them (the state of any guest / freshly signed-up user) by calling the SDK. It used `req.app.get('audiusSdk').full.users.getUserAccount(...)`, but the @audius/sdk instance has no `.full` namespace - `users` is a top-level API. So `.full` is undefined and `.users` throws a synchronous TypeError ("Cannot read properties of undefined (reading 'users')") on EVERY new-user auth request (/users/update, /record_ip, etc). Confirmed in prod logs: TypeError: Cannot read properties of undefined (reading 'users') at authMiddleware (build/src/authMiddleware.js:97:68) msg: "Failed to update blockchainUserId/handle" The bad accessor came in with the monorepo import (#14388) and only began firing once #14474 (6/15) made loadAudiusSdk.cjs available so the SDK actually initialized - matching the signup regression window. The surrounding try/catch swallowed the error and called next(), so the backfill silently never happened for new users. Fix: use the correct accessor `audiusSdk.users.getUserAccount`. Also wrap the now-live call in a 3s timeout (deferred into a promise so a missing/misshapen sdk rejects instead of throwing synchronously), so that once the call actually runs, a slow discovery lookup for a not-yet-indexed new user degrades gracefully (logged, then next()) instead of stalling auth. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0f000be commit 7838f7d

1 file changed

Lines changed: 42 additions & 10 deletions

File tree

packages/identity-service/src/authMiddleware.js

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ const models = require('./models')
1111
const audiusLibsWrapper = require('./audiusLibsInstance')
1212
const { encodeHashId, decodeHashId } = require('./utils/hashIds')
1313

14+
// Upper bound on the discovery/SDK lookup used to backfill blockchainUserId/handle.
15+
// During signup the on-chain user is often not yet indexed by discovery, so this
16+
// call can block on the SDK's internal node selection + retries. Without a bound it
17+
// stalls the entire request (e.g. /users/update) until the client times out.
18+
const SDK_USER_LOOKUP_TIMEOUT_MS = 3000
19+
20+
const withTimeout = (promise, ms, message) =>
21+
Promise.race([
22+
promise,
23+
new Promise((_resolve, reject) =>
24+
setTimeout(() => reject(new Error(message)), ms)
25+
)
26+
])
27+
1428
/**
1529
* Queries for whether the wallet address has privilege to act as actingUserId
1630
* @param {number} managerWalletAddress
@@ -114,11 +128,20 @@ async function authMiddleware(req, res, next) {
114128
// ensuring that the user.handle always represents the latest state on chain
115129
if (!user.blockchainUserId || !user.handle) {
116130
try {
117-
const res = await req.app.get('audiusSdk').full.users.getUserAccount({
118-
wallet: walletAddress,
119-
encodedDataMessage,
120-
encodedDataSignature: signature
121-
})
131+
const res = await withTimeout(
132+
// Defer property access into the promise so a missing/misshapen sdk
133+
// surfaces as a rejection (handled below) rather than a synchronous
134+
// throw, and so the timeout always applies.
135+
Promise.resolve().then(() =>
136+
req.app.get('audiusSdk').users.getUserAccount({
137+
wallet: walletAddress,
138+
encodedDataMessage,
139+
encodedDataSignature: signature
140+
})
141+
),
142+
SDK_USER_LOOKUP_TIMEOUT_MS,
143+
'audiusSdk.getUserAccount timed out'
144+
)
122145
const discprovUser = res.data.user
123146
const userId = decodeHashId(discprovUser.id)
124147
const handle = discprovUser.handle
@@ -181,11 +204,20 @@ const parameterizedAuthMiddleware = ({ shouldRespondBadRequest }) => {
181204

182205
if (!user.blockchainUserId || !user.handle) {
183206
try {
184-
const res = await req.app.get('audiusSdk').full.users.getUserAccount({
185-
wallet: walletAddress,
186-
encodedDataMessage,
187-
encodedDataSignature: signature
188-
})
207+
const res = await withTimeout(
208+
// Defer property access into the promise so a missing/misshapen sdk
209+
// surfaces as a rejection (handled below) rather than a synchronous
210+
// throw, and so the timeout always applies.
211+
Promise.resolve().then(() =>
212+
req.app.get('audiusSdk').users.getUserAccount({
213+
wallet: walletAddress,
214+
encodedDataMessage,
215+
encodedDataSignature: signature
216+
})
217+
),
218+
SDK_USER_LOOKUP_TIMEOUT_MS,
219+
'audiusSdk.getUserAccount timed out'
220+
)
189221
const discprovUser = res.data.user
190222
const userId = decodeHashId(discprovUser.id)
191223
const handle = discprovUser.handle

0 commit comments

Comments
 (0)