[{"data":1,"prerenderedAt":1578},["ShallowReactive",2],{"navigation":3,"\u002Fgetting-started\u002Fauthentication":111,"\u002Fgetting-started\u002Fauthentication-surround":1573},[4,38,77,97,104],{"title":5,"path":6,"stem":7,"children":8,"icon":37},"Getting Started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12,17,22,27,32],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-house",{"title":13,"path":14,"stem":15,"icon":16},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":18,"path":19,"stem":20,"icon":21},"Configuration","\u002Fgetting-started\u002Fconfiguration","1.getting-started\u002F3.configuration","i-lucide-settings",{"title":23,"path":24,"stem":25,"icon":26},"Usage","\u002Fgetting-started\u002Fusage","1.getting-started\u002F4.usage","i-lucide-code",{"title":28,"path":29,"stem":30,"icon":31},"Authentication","\u002Fgetting-started\u002Fauthentication","1.getting-started\u002F5.authentication","i-lucide-lock",{"title":33,"path":34,"stem":35,"icon":36},"DevTools","\u002Fgetting-started\u002Fdevtools","1.getting-started\u002F6.devtools","i-lucide-radio-tower",false,{"title":39,"icon":26,"path":40,"stem":41,"children":42,"page":37},"Composables","\u002Fcomposables","2.composables",[43,48,53,58,63,67,72],{"title":44,"path":45,"stem":46,"icon":47},"useRealtimeState","\u002Fcomposables\u002Fuserealtimestate","2.composables\u002F1.useRealtimeState","i-lucide-refresh-cw",{"title":49,"path":50,"stem":51,"icon":52},"useRealtimeEvents","\u002Fcomposables\u002Fuserealtimeevents","2.composables\u002F2.useRealtimeEvents","i-lucide-radio",{"title":54,"path":55,"stem":56,"icon":57},"useRealtimeConnection","\u002Fcomposables\u002Fuserealtimeconnection","2.composables\u002F3.useRealtimeConnection","i-lucide-wifi",{"title":59,"path":60,"stem":61,"icon":62},"useRealtimePresence","\u002Fcomposables\u002Fuserealtimepresence","2.composables\u002F4.useRealtimePresence","i-lucide-users",{"title":64,"path":65,"stem":66,"icon":31},"useRealtimeLock","\u002Fcomposables\u002Fuserealtimelock","2.composables\u002F5.useRealtimeLock",{"title":68,"path":69,"stem":70,"icon":71},"useRealtimeLockRoom","\u002Fcomposables\u002Fuserealtimelockroom","2.composables\u002F6.useRealtimeLockRoom","i-lucide-list-checks",{"title":73,"path":74,"stem":75,"icon":76},"useRealtimeRoom","\u002Fcomposables\u002Fuserealtimeroom","2.composables\u002F7.useRealtimeRoom","i-lucide-door-open",{"title":78,"icon":79,"path":80,"stem":81,"children":82,"page":37},"Technical","i-lucide-cpu","\u002Ftechnical","3.technical",[83,88,92],{"title":84,"path":85,"stem":86,"icon":87},"Architecture","\u002Ftechnical\u002Farchitecture","3.technical\u002F1.architecture","i-lucide-network",{"title":89,"path":90,"stem":91,"icon":52},"Notification Layer","\u002Ftechnical\u002Fpubsub","3.technical\u002F2.pubsub",{"title":93,"path":94,"stem":95,"icon":96},"Multi-Server Sync","\u002Ftechnical\u002Fcross-server-sync","3.technical\u002F3.cross-server-sync","i-lucide-server",{"title":98,"path":99,"stem":100,"children":101,"icon":103},"Blocks","\u002Fblocks","4.blocks\u002F1.index",[102],{"title":98,"path":99,"stem":100,"icon":103},"i-lucide-layout-grid",{"title":105,"path":106,"stem":107,"children":108,"icon":110},"Components","\u002Fcomponents","5.components\u002F1.index",[109],{"title":105,"path":106,"stem":107,"icon":110},"i-lucide-component",{"id":112,"title":28,"body":113,"description":1566,"extension":1567,"links":1568,"meta":1569,"navigation":1570,"path":29,"seo":1571,"stem":30,"__hash__":1572},"docs\u002F1.getting-started\u002F5.authentication.md",{"type":114,"value":115,"toc":1559},"minimark",[116,133,138,154,314,318,329,428,431,521,524,843,849,853,860,1224,1231,1260,1267,1538,1555],[117,118,119,120,124,125,128,129,132],"p",{},"Nuxt Realtime exposes the Socket.IO ",[121,122,123],"code",{},"Server"," instance through the ",[121,126,127],{},"nuxt-realtime:io"," Nitro hook before any connections are accepted. Register ",[121,130,131],{},"io.use()"," middleware there to authenticate or authorize clients.",[134,135,137],"h2",{"id":136},"how-it-works","How it works",[117,139,140,141,143,144,146,147,150,151,153],{},"Create a Nitro server plugin and hook into ",[121,142,127],{},". The hook fires after the ",[121,145,123],{}," is configured but before it is bound to the transport and before ",[121,148,149],{},"connection"," handlers are wired up, so every ",[121,152,131],{}," middleware registered here runs for every incoming connection.",[155,156,162],"pre",{"className":157,"code":158,"filename":159,"language":160,"meta":161,"style":161},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('nuxt-realtime:io', (io) => {\n    io.use((socket, next) => {\n      \u002F\u002F authenticate here: call next() to allow, next(new Error(...)) to reject\n      next()\n    })\n  })\n})\n","server\u002Fplugins\u002Frealtime-auth.ts","ts","",[121,163,164,201,244,273,280,289,298,306],{"__ignoreMap":161},[165,166,169,173,176,180,184,187,191,194,198],"span",{"class":167,"line":168},"line",1,[165,170,172],{"class":171},"s7zQu","export",[165,174,175],{"class":171}," default",[165,177,179],{"class":178},"s2Zo4"," defineNitroPlugin",[165,181,183],{"class":182},"sTEyZ","(",[165,185,183],{"class":186},"sMK4o",[165,188,190],{"class":189},"sHdIc","nitroApp",[165,192,193],{"class":186},")",[165,195,197],{"class":196},"spNyl"," =>",[165,199,200],{"class":186}," {\n",[165,202,204,207,210,213,215,218,221,224,227,229,232,235,238,240,242],{"class":167,"line":203},2,[165,205,206],{"class":182},"  nitroApp",[165,208,209],{"class":186},".",[165,211,212],{"class":182},"hooks",[165,214,209],{"class":186},[165,216,217],{"class":178},"hook",[165,219,183],{"class":220},"swJcz",[165,222,223],{"class":186},"'",[165,225,127],{"class":226},"sfazB",[165,228,223],{"class":186},[165,230,231],{"class":186},",",[165,233,234],{"class":186}," (",[165,236,237],{"class":189},"io",[165,239,193],{"class":186},[165,241,197],{"class":196},[165,243,200],{"class":186},[165,245,247,250,252,255,257,259,262,264,267,269,271],{"class":167,"line":246},3,[165,248,249],{"class":182},"    io",[165,251,209],{"class":186},[165,253,254],{"class":178},"use",[165,256,183],{"class":220},[165,258,183],{"class":186},[165,260,261],{"class":189},"socket",[165,263,231],{"class":186},[165,265,266],{"class":189}," next",[165,268,193],{"class":186},[165,270,197],{"class":196},[165,272,200],{"class":186},[165,274,276],{"class":167,"line":275},4,[165,277,279],{"class":278},"sHwdD","      \u002F\u002F authenticate here: call next() to allow, next(new Error(...)) to reject\n",[165,281,283,286],{"class":167,"line":282},5,[165,284,285],{"class":178},"      next",[165,287,288],{"class":220},"()\n",[165,290,292,295],{"class":167,"line":291},6,[165,293,294],{"class":186},"    }",[165,296,297],{"class":220},")\n",[165,299,301,304],{"class":167,"line":300},7,[165,302,303],{"class":186},"  }",[165,305,297],{"class":220},[165,307,309,312],{"class":167,"line":308},8,[165,310,311],{"class":186},"}",[165,313,297],{"class":182},[134,315,317],{"id":316},"jwt-based-authentication","JWT-based authentication",[117,319,320,321,324,325,328],{},"Nuxt Realtime creates the client socket for you, so you can't call ",[121,322,323],{},"io({ auth: ... })"," directly. Instead, register a ",[121,326,327],{},"nuxt-realtime:auth"," app hook. It fires before every connection attempt, including reconnects, so you can supply a fresh token each time instead of baking one in at initial connect:",[155,330,333],{"className":157,"code":331,"filename":332,"language":160,"meta":161,"style":161},"export default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.hook('nuxt-realtime:auth', (ctx) => {\n    ctx.auth.token = useAuthToken().value\n  })\n})\n","plugins\u002Frealtime-auth.client.ts",[121,334,335,357,387,416,422],{"__ignoreMap":161},[165,336,337,339,341,344,346,348,351,353,355],{"class":167,"line":168},[165,338,172],{"class":171},[165,340,175],{"class":171},[165,342,343],{"class":178}," defineNuxtPlugin",[165,345,183],{"class":182},[165,347,183],{"class":186},[165,349,350],{"class":189},"nuxtApp",[165,352,193],{"class":186},[165,354,197],{"class":196},[165,356,200],{"class":186},[165,358,359,362,364,366,368,370,372,374,376,378,381,383,385],{"class":167,"line":203},[165,360,361],{"class":182},"  nuxtApp",[165,363,209],{"class":186},[165,365,217],{"class":178},[165,367,183],{"class":220},[165,369,223],{"class":186},[165,371,327],{"class":226},[165,373,223],{"class":186},[165,375,231],{"class":186},[165,377,234],{"class":186},[165,379,380],{"class":189},"ctx",[165,382,193],{"class":186},[165,384,197],{"class":196},[165,386,200],{"class":186},[165,388,389,392,394,397,399,402,405,408,411,413],{"class":167,"line":246},[165,390,391],{"class":182},"    ctx",[165,393,209],{"class":186},[165,395,396],{"class":182},"auth",[165,398,209],{"class":186},[165,400,401],{"class":182},"token",[165,403,404],{"class":186}," =",[165,406,407],{"class":178}," useAuthToken",[165,409,410],{"class":220},"()",[165,412,209],{"class":186},[165,414,415],{"class":182},"value\n",[165,417,418,420],{"class":167,"line":275},[165,419,303],{"class":186},[165,421,297],{"class":220},[165,423,424,426],{"class":167,"line":282},[165,425,311],{"class":186},[165,427,297],{"class":182},[117,429,430],{},"For a token that expires and needs refreshing on reconnect, fetch it inside the hook instead of reading a cached value:",[155,432,434],{"className":157,"code":433,"filename":332,"language":160,"meta":161,"style":161},"export default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.hook('nuxt-realtime:auth', async (ctx) => {\n    ctx.auth.token = await fetchFreshToken()\n  })\n})\n",[121,435,436,456,487,509,515],{"__ignoreMap":161},[165,437,438,440,442,444,446,448,450,452,454],{"class":167,"line":168},[165,439,172],{"class":171},[165,441,175],{"class":171},[165,443,343],{"class":178},[165,445,183],{"class":182},[165,447,183],{"class":186},[165,449,350],{"class":189},[165,451,193],{"class":186},[165,453,197],{"class":196},[165,455,200],{"class":186},[165,457,458,460,462,464,466,468,470,472,474,477,479,481,483,485],{"class":167,"line":203},[165,459,361],{"class":182},[165,461,209],{"class":186},[165,463,217],{"class":178},[165,465,183],{"class":220},[165,467,223],{"class":186},[165,469,327],{"class":226},[165,471,223],{"class":186},[165,473,231],{"class":186},[165,475,476],{"class":196}," async",[165,478,234],{"class":186},[165,480,380],{"class":189},[165,482,193],{"class":186},[165,484,197],{"class":196},[165,486,200],{"class":186},[165,488,489,491,493,495,497,499,501,504,507],{"class":167,"line":246},[165,490,391],{"class":182},[165,492,209],{"class":186},[165,494,396],{"class":182},[165,496,209],{"class":186},[165,498,401],{"class":182},[165,500,404],{"class":186},[165,502,503],{"class":171}," await",[165,505,506],{"class":178}," fetchFreshToken",[165,508,288],{"class":220},[165,510,511,513],{"class":167,"line":275},[165,512,303],{"class":186},[165,514,297],{"class":220},[165,516,517,519],{"class":167,"line":282},[165,518,311],{"class":186},[165,520,297],{"class":182},[117,522,523],{},"Verify it on the server:",[155,525,527],{"className":157,"code":526,"filename":159,"language":160,"meta":161,"style":161},"import jwt from 'jsonwebtoken'\n\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('nuxt-realtime:io', (io) => {\n    io.use((socket, next) => {\n      const token = socket.handshake.auth?.token\n      if (!token) return next(new Error('Unauthorized'))\n\n      try {\n        const payload = jwt.verify(token, process.env.JWT_SECRET!)\n        socket.data.user = payload\n        next()\n      }\n      catch {\n        next(new Error('Unauthorized'))\n      }\n    })\n  })\n})\n",[121,528,529,549,555,575,607,631,659,699,703,711,753,774,782,788,796,817,822,829,836],{"__ignoreMap":161},[165,530,531,534,537,540,543,546],{"class":167,"line":168},[165,532,533],{"class":171},"import",[165,535,536],{"class":182}," jwt ",[165,538,539],{"class":171},"from",[165,541,542],{"class":186}," '",[165,544,545],{"class":226},"jsonwebtoken",[165,547,548],{"class":186},"'\n",[165,550,551],{"class":167,"line":203},[165,552,554],{"emptyLinePlaceholder":553},true,"\n",[165,556,557,559,561,563,565,567,569,571,573],{"class":167,"line":246},[165,558,172],{"class":171},[165,560,175],{"class":171},[165,562,179],{"class":178},[165,564,183],{"class":182},[165,566,183],{"class":186},[165,568,190],{"class":189},[165,570,193],{"class":186},[165,572,197],{"class":196},[165,574,200],{"class":186},[165,576,577,579,581,583,585,587,589,591,593,595,597,599,601,603,605],{"class":167,"line":275},[165,578,206],{"class":182},[165,580,209],{"class":186},[165,582,212],{"class":182},[165,584,209],{"class":186},[165,586,217],{"class":178},[165,588,183],{"class":220},[165,590,223],{"class":186},[165,592,127],{"class":226},[165,594,223],{"class":186},[165,596,231],{"class":186},[165,598,234],{"class":186},[165,600,237],{"class":189},[165,602,193],{"class":186},[165,604,197],{"class":196},[165,606,200],{"class":186},[165,608,609,611,613,615,617,619,621,623,625,627,629],{"class":167,"line":282},[165,610,249],{"class":182},[165,612,209],{"class":186},[165,614,254],{"class":178},[165,616,183],{"class":220},[165,618,183],{"class":186},[165,620,261],{"class":189},[165,622,231],{"class":186},[165,624,266],{"class":189},[165,626,193],{"class":186},[165,628,197],{"class":196},[165,630,200],{"class":186},[165,632,633,636,639,641,644,646,649,651,653,656],{"class":167,"line":291},[165,634,635],{"class":196},"      const",[165,637,638],{"class":182}," token",[165,640,404],{"class":186},[165,642,643],{"class":182}," socket",[165,645,209],{"class":186},[165,647,648],{"class":182},"handshake",[165,650,209],{"class":186},[165,652,396],{"class":182},[165,654,655],{"class":186},"?.",[165,657,658],{"class":182},"token\n",[165,660,661,664,666,669,671,674,677,679,681,684,687,689,691,694,696],{"class":167,"line":300},[165,662,663],{"class":171},"      if",[165,665,234],{"class":220},[165,667,668],{"class":186},"!",[165,670,401],{"class":182},[165,672,673],{"class":220},") ",[165,675,676],{"class":171},"return",[165,678,266],{"class":178},[165,680,183],{"class":220},[165,682,683],{"class":186},"new",[165,685,686],{"class":178}," Error",[165,688,183],{"class":220},[165,690,223],{"class":186},[165,692,693],{"class":226},"Unauthorized",[165,695,223],{"class":186},[165,697,698],{"class":220},"))\n",[165,700,701],{"class":167,"line":308},[165,702,554],{"emptyLinePlaceholder":553},[165,704,706,709],{"class":167,"line":705},9,[165,707,708],{"class":171},"      try",[165,710,200],{"class":186},[165,712,714,717,720,722,725,727,730,732,734,736,739,741,744,746,749,751],{"class":167,"line":713},10,[165,715,716],{"class":196},"        const",[165,718,719],{"class":182}," payload",[165,721,404],{"class":186},[165,723,724],{"class":182}," jwt",[165,726,209],{"class":186},[165,728,729],{"class":178},"verify",[165,731,183],{"class":220},[165,733,401],{"class":182},[165,735,231],{"class":186},[165,737,738],{"class":182}," process",[165,740,209],{"class":186},[165,742,743],{"class":182},"env",[165,745,209],{"class":186},[165,747,748],{"class":182},"JWT_SECRET",[165,750,668],{"class":186},[165,752,297],{"class":220},[165,754,756,759,761,764,766,769,771],{"class":167,"line":755},11,[165,757,758],{"class":182},"        socket",[165,760,209],{"class":186},[165,762,763],{"class":182},"data",[165,765,209],{"class":186},[165,767,768],{"class":182},"user",[165,770,404],{"class":186},[165,772,773],{"class":182}," payload\n",[165,775,777,780],{"class":167,"line":776},12,[165,778,779],{"class":178},"        next",[165,781,288],{"class":220},[165,783,785],{"class":167,"line":784},13,[165,786,787],{"class":186},"      }\n",[165,789,791,794],{"class":167,"line":790},14,[165,792,793],{"class":171},"      catch",[165,795,200],{"class":186},[165,797,799,801,803,805,807,809,811,813,815],{"class":167,"line":798},15,[165,800,779],{"class":178},[165,802,183],{"class":220},[165,804,683],{"class":186},[165,806,686],{"class":178},[165,808,183],{"class":220},[165,810,223],{"class":186},[165,812,693],{"class":226},[165,814,223],{"class":186},[165,816,698],{"class":220},[165,818,820],{"class":167,"line":819},16,[165,821,787],{"class":186},[165,823,825,827],{"class":167,"line":824},17,[165,826,294],{"class":186},[165,828,297],{"class":220},[165,830,832,834],{"class":167,"line":831},18,[165,833,303],{"class":186},[165,835,297],{"class":220},[165,837,839,841],{"class":167,"line":838},19,[165,840,311],{"class":186},[165,842,297],{"class":182},[117,844,845,846,848],{},"The middleware rejects unauthenticated connections before a ",[121,847,149],{}," event is ever emitted.",[134,850,852],{"id":851},"session-cookie-based-authentication","Session \u002F cookie-based authentication",[117,854,855,856,859],{},"Read the session cookie from the underlying HTTP request exposed via ",[121,857,858],{},"socket.request",":",[155,861,863],{"className":157,"code":862,"filename":159,"language":160,"meta":161,"style":161},"import { parse } from 'cookie'\nimport { unsealData } from 'iron-session'\n\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('nuxt-realtime:io', (io) => {\n    io.use(async (socket, next) => {\n      const cookies = parse(socket.request.headers.cookie ?? '')\n      const sessionCookie = cookies['session']\n\n      if (!sessionCookie) return next(new Error('Unauthorized'))\n\n      try {\n        const session = await unsealData(sessionCookie, { password: process.env.SESSION_SECRET! })\n        socket.data.user = session.user\n        next()\n      }\n      catch {\n        next(new Error('Unauthorized'))\n      }\n    })\n  })\n})\n",[121,864,865,888,908,912,932,964,991,1028,1052,1056,1089,1093,1099,1142,1163,1169,1173,1179,1199,1203,1210,1217],{"__ignoreMap":161},[165,866,867,869,872,875,878,881,883,886],{"class":167,"line":168},[165,868,533],{"class":171},[165,870,871],{"class":186}," {",[165,873,874],{"class":182}," parse",[165,876,877],{"class":186}," }",[165,879,880],{"class":171}," from",[165,882,542],{"class":186},[165,884,885],{"class":226},"cookie",[165,887,548],{"class":186},[165,889,890,892,894,897,899,901,903,906],{"class":167,"line":203},[165,891,533],{"class":171},[165,893,871],{"class":186},[165,895,896],{"class":182}," unsealData",[165,898,877],{"class":186},[165,900,880],{"class":171},[165,902,542],{"class":186},[165,904,905],{"class":226},"iron-session",[165,907,548],{"class":186},[165,909,910],{"class":167,"line":246},[165,911,554],{"emptyLinePlaceholder":553},[165,913,914,916,918,920,922,924,926,928,930],{"class":167,"line":275},[165,915,172],{"class":171},[165,917,175],{"class":171},[165,919,179],{"class":178},[165,921,183],{"class":182},[165,923,183],{"class":186},[165,925,190],{"class":189},[165,927,193],{"class":186},[165,929,197],{"class":196},[165,931,200],{"class":186},[165,933,934,936,938,940,942,944,946,948,950,952,954,956,958,960,962],{"class":167,"line":282},[165,935,206],{"class":182},[165,937,209],{"class":186},[165,939,212],{"class":182},[165,941,209],{"class":186},[165,943,217],{"class":178},[165,945,183],{"class":220},[165,947,223],{"class":186},[165,949,127],{"class":226},[165,951,223],{"class":186},[165,953,231],{"class":186},[165,955,234],{"class":186},[165,957,237],{"class":189},[165,959,193],{"class":186},[165,961,197],{"class":196},[165,963,200],{"class":186},[165,965,966,968,970,972,974,977,979,981,983,985,987,989],{"class":167,"line":291},[165,967,249],{"class":182},[165,969,209],{"class":186},[165,971,254],{"class":178},[165,973,183],{"class":220},[165,975,976],{"class":196},"async",[165,978,234],{"class":186},[165,980,261],{"class":189},[165,982,231],{"class":186},[165,984,266],{"class":189},[165,986,193],{"class":186},[165,988,197],{"class":196},[165,990,200],{"class":186},[165,992,993,995,998,1000,1002,1004,1006,1008,1011,1013,1016,1018,1020,1023,1026],{"class":167,"line":300},[165,994,635],{"class":196},[165,996,997],{"class":182}," cookies",[165,999,404],{"class":186},[165,1001,874],{"class":178},[165,1003,183],{"class":220},[165,1005,261],{"class":182},[165,1007,209],{"class":186},[165,1009,1010],{"class":182},"request",[165,1012,209],{"class":186},[165,1014,1015],{"class":182},"headers",[165,1017,209],{"class":186},[165,1019,885],{"class":182},[165,1021,1022],{"class":186}," ??",[165,1024,1025],{"class":186}," ''",[165,1027,297],{"class":220},[165,1029,1030,1032,1035,1037,1039,1042,1044,1047,1049],{"class":167,"line":308},[165,1031,635],{"class":196},[165,1033,1034],{"class":182}," sessionCookie",[165,1036,404],{"class":186},[165,1038,997],{"class":182},[165,1040,1041],{"class":220},"[",[165,1043,223],{"class":186},[165,1045,1046],{"class":226},"session",[165,1048,223],{"class":186},[165,1050,1051],{"class":220},"]\n",[165,1053,1054],{"class":167,"line":705},[165,1055,554],{"emptyLinePlaceholder":553},[165,1057,1058,1060,1062,1064,1067,1069,1071,1073,1075,1077,1079,1081,1083,1085,1087],{"class":167,"line":713},[165,1059,663],{"class":171},[165,1061,234],{"class":220},[165,1063,668],{"class":186},[165,1065,1066],{"class":182},"sessionCookie",[165,1068,673],{"class":220},[165,1070,676],{"class":171},[165,1072,266],{"class":178},[165,1074,183],{"class":220},[165,1076,683],{"class":186},[165,1078,686],{"class":178},[165,1080,183],{"class":220},[165,1082,223],{"class":186},[165,1084,693],{"class":226},[165,1086,223],{"class":186},[165,1088,698],{"class":220},[165,1090,1091],{"class":167,"line":755},[165,1092,554],{"emptyLinePlaceholder":553},[165,1094,1095,1097],{"class":167,"line":776},[165,1096,708],{"class":171},[165,1098,200],{"class":186},[165,1100,1101,1103,1106,1108,1110,1112,1114,1116,1118,1120,1123,1125,1127,1129,1131,1133,1136,1138,1140],{"class":167,"line":784},[165,1102,716],{"class":196},[165,1104,1105],{"class":182}," session",[165,1107,404],{"class":186},[165,1109,503],{"class":171},[165,1111,896],{"class":178},[165,1113,183],{"class":220},[165,1115,1066],{"class":182},[165,1117,231],{"class":186},[165,1119,871],{"class":186},[165,1121,1122],{"class":220}," password",[165,1124,859],{"class":186},[165,1126,738],{"class":182},[165,1128,209],{"class":186},[165,1130,743],{"class":182},[165,1132,209],{"class":186},[165,1134,1135],{"class":182},"SESSION_SECRET",[165,1137,668],{"class":186},[165,1139,877],{"class":186},[165,1141,297],{"class":220},[165,1143,1144,1146,1148,1150,1152,1154,1156,1158,1160],{"class":167,"line":790},[165,1145,758],{"class":182},[165,1147,209],{"class":186},[165,1149,763],{"class":182},[165,1151,209],{"class":186},[165,1153,768],{"class":182},[165,1155,404],{"class":186},[165,1157,1105],{"class":182},[165,1159,209],{"class":186},[165,1161,1162],{"class":182},"user\n",[165,1164,1165,1167],{"class":167,"line":798},[165,1166,779],{"class":178},[165,1168,288],{"class":220},[165,1170,1171],{"class":167,"line":819},[165,1172,787],{"class":186},[165,1174,1175,1177],{"class":167,"line":824},[165,1176,793],{"class":171},[165,1178,200],{"class":186},[165,1180,1181,1183,1185,1187,1189,1191,1193,1195,1197],{"class":167,"line":831},[165,1182,779],{"class":178},[165,1184,183],{"class":220},[165,1186,683],{"class":186},[165,1188,686],{"class":178},[165,1190,183],{"class":220},[165,1192,223],{"class":186},[165,1194,693],{"class":226},[165,1196,223],{"class":186},[165,1198,698],{"class":220},[165,1200,1201],{"class":167,"line":838},[165,1202,787],{"class":186},[165,1204,1206,1208],{"class":167,"line":1205},20,[165,1207,294],{"class":186},[165,1209,297],{"class":220},[165,1211,1213,1215],{"class":167,"line":1212},21,[165,1214,303],{"class":186},[165,1216,297],{"class":220},[165,1218,1220,1222],{"class":167,"line":1219},22,[165,1221,311],{"class":186},[165,1223,297],{"class":182},[134,1225,1227,1228],{"id":1226},"gating-channels-with-socketdata","Gating channels with ",[121,1229,1230],{},"socket.data",[1232,1233,1236],"callout",{"color":1234,"icon":1235},"warning","i-lucide-triangle-alert",[117,1237,1238,1241,1242,1245,1246,1251,1252,1256,1257,1259],{},[121,1239,1240],{},"event:subscribe"," and ",[121,1243,1244],{},"event:publish"," (used by ",[1247,1248,1249],"a",{"href":50},[121,1250,49],{},") are handled internally and always join\u002Fbroadcast — a handler you register for the same event name runs ",[1253,1254,1255],"em",{},"alongside"," the built-in one, not instead of it, so it cannot block the join. Gate channel access on your own custom events instead, or restrict who can connect at all via ",[121,1258,131],{}," above.",[117,1261,1262,1263,1266],{},"Once authentication sets ",[121,1264,1265],{},"socket.data.user",", use it in your own event handlers to guard access to your own channels:",[155,1268,1271],{"className":157,"code":1269,"filename":1270,"language":160,"meta":161,"style":161},"export default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('nuxt-realtime:io', (io) => {\n    io.on('connection', (socket) => {\n      socket.on('room:join', (channel: string) => {\n        const user = socket.data.user\n        if (!canAccessChannel(user, channel)) {\n          socket.emit('error', { message: 'Forbidden' })\n          return\n        }\n        socket.join(`room:${channel}`)\n      })\n    })\n  })\n})\n","server\u002Fplugins\u002Frealtime-channel-guard.ts",[121,1272,1273,1293,1325,1354,1391,1410,1437,1476,1481,1486,1513,1520,1526,1532],{"__ignoreMap":161},[165,1274,1275,1277,1279,1281,1283,1285,1287,1289,1291],{"class":167,"line":168},[165,1276,172],{"class":171},[165,1278,175],{"class":171},[165,1280,179],{"class":178},[165,1282,183],{"class":182},[165,1284,183],{"class":186},[165,1286,190],{"class":189},[165,1288,193],{"class":186},[165,1290,197],{"class":196},[165,1292,200],{"class":186},[165,1294,1295,1297,1299,1301,1303,1305,1307,1309,1311,1313,1315,1317,1319,1321,1323],{"class":167,"line":203},[165,1296,206],{"class":182},[165,1298,209],{"class":186},[165,1300,212],{"class":182},[165,1302,209],{"class":186},[165,1304,217],{"class":178},[165,1306,183],{"class":220},[165,1308,223],{"class":186},[165,1310,127],{"class":226},[165,1312,223],{"class":186},[165,1314,231],{"class":186},[165,1316,234],{"class":186},[165,1318,237],{"class":189},[165,1320,193],{"class":186},[165,1322,197],{"class":196},[165,1324,200],{"class":186},[165,1326,1327,1329,1331,1334,1336,1338,1340,1342,1344,1346,1348,1350,1352],{"class":167,"line":246},[165,1328,249],{"class":182},[165,1330,209],{"class":186},[165,1332,1333],{"class":178},"on",[165,1335,183],{"class":220},[165,1337,223],{"class":186},[165,1339,149],{"class":226},[165,1341,223],{"class":186},[165,1343,231],{"class":186},[165,1345,234],{"class":186},[165,1347,261],{"class":189},[165,1349,193],{"class":186},[165,1351,197],{"class":196},[165,1353,200],{"class":186},[165,1355,1356,1359,1361,1363,1365,1367,1370,1372,1374,1376,1379,1381,1385,1387,1389],{"class":167,"line":275},[165,1357,1358],{"class":182},"      socket",[165,1360,209],{"class":186},[165,1362,1333],{"class":178},[165,1364,183],{"class":220},[165,1366,223],{"class":186},[165,1368,1369],{"class":226},"room:join",[165,1371,223],{"class":186},[165,1373,231],{"class":186},[165,1375,234],{"class":186},[165,1377,1378],{"class":189},"channel",[165,1380,859],{"class":186},[165,1382,1384],{"class":1383},"sBMFI"," string",[165,1386,193],{"class":186},[165,1388,197],{"class":196},[165,1390,200],{"class":186},[165,1392,1393,1395,1398,1400,1402,1404,1406,1408],{"class":167,"line":282},[165,1394,716],{"class":196},[165,1396,1397],{"class":182}," user",[165,1399,404],{"class":186},[165,1401,643],{"class":182},[165,1403,209],{"class":186},[165,1405,763],{"class":182},[165,1407,209],{"class":186},[165,1409,1162],{"class":182},[165,1411,1412,1415,1417,1419,1422,1424,1426,1428,1431,1434],{"class":167,"line":291},[165,1413,1414],{"class":171},"        if",[165,1416,234],{"class":220},[165,1418,668],{"class":186},[165,1420,1421],{"class":178},"canAccessChannel",[165,1423,183],{"class":220},[165,1425,768],{"class":182},[165,1427,231],{"class":186},[165,1429,1430],{"class":182}," channel",[165,1432,1433],{"class":220},")) ",[165,1435,1436],{"class":186},"{\n",[165,1438,1439,1442,1444,1447,1449,1451,1454,1456,1458,1460,1463,1465,1467,1470,1472,1474],{"class":167,"line":300},[165,1440,1441],{"class":182},"          socket",[165,1443,209],{"class":186},[165,1445,1446],{"class":178},"emit",[165,1448,183],{"class":220},[165,1450,223],{"class":186},[165,1452,1453],{"class":226},"error",[165,1455,223],{"class":186},[165,1457,231],{"class":186},[165,1459,871],{"class":186},[165,1461,1462],{"class":220}," message",[165,1464,859],{"class":186},[165,1466,542],{"class":186},[165,1468,1469],{"class":226},"Forbidden",[165,1471,223],{"class":186},[165,1473,877],{"class":186},[165,1475,297],{"class":220},[165,1477,1478],{"class":167,"line":308},[165,1479,1480],{"class":171},"          return\n",[165,1482,1483],{"class":167,"line":705},[165,1484,1485],{"class":186},"        }\n",[165,1487,1488,1490,1492,1495,1497,1500,1503,1506,1508,1511],{"class":167,"line":713},[165,1489,758],{"class":182},[165,1491,209],{"class":186},[165,1493,1494],{"class":178},"join",[165,1496,183],{"class":220},[165,1498,1499],{"class":186},"`",[165,1501,1502],{"class":226},"room:",[165,1504,1505],{"class":186},"${",[165,1507,1378],{"class":182},[165,1509,1510],{"class":186},"}`",[165,1512,297],{"class":220},[165,1514,1515,1518],{"class":167,"line":755},[165,1516,1517],{"class":186},"      }",[165,1519,297],{"class":220},[165,1521,1522,1524],{"class":167,"line":776},[165,1523,294],{"class":186},[165,1525,297],{"class":220},[165,1527,1528,1530],{"class":167,"line":784},[165,1529,303],{"class":186},[165,1531,297],{"class":220},[165,1533,1534,1536],{"class":167,"line":790},[165,1535,311],{"class":186},[165,1537,297],{"class":182},[1232,1539,1542],{"color":1540,"icon":1541},"info","i-lucide-info",[117,1543,1544,1546,1547,1550,1551,1554],{},[121,1545,1230],{}," is typed as ",[121,1548,1549],{},"any"," by default. You can narrow it by extending Socket.IO's ",[121,1552,1553],{},"SocketData"," interface in a type definition file in your project.",[1556,1557,1558],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":161,"searchDepth":168,"depth":203,"links":1560},[1561,1562,1563,1564],{"id":136,"depth":203,"text":137},{"id":316,"depth":203,"text":317},{"id":851,"depth":203,"text":852},{"id":1226,"depth":203,"text":1565},"Gating channels with socket.data","Authenticate and authorize Socket.IO clients using the nuxt-realtime:io hook.","md",null,{},{"icon":31},{"title":28,"description":1566},"bpjrcTlBD-NNhxSEcUfQ36dyol7ECucWzJAVW32nLP8",[1574,1576],{"title":23,"path":24,"stem":25,"description":1575,"icon":26,"children":-1},"Quick overview of the Nuxt Realtime composables.",{"title":33,"path":34,"stem":35,"description":1577,"icon":36,"children":-1},"The \"Realtime\" Nuxt DevTools tab for inspecting connections, storage, and events.",1787657973112]