[{"data":1,"prerenderedAt":892},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Ftokens":116,"\u002Fguides\u002Ftokens-surround":887},[4,23,61,82,108,112],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":22},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,14,18],{"title":11,"path":12,"stem":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction",{"title":15,"path":16,"stem":17},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":19,"path":20,"stem":21},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start",false,{"title":24,"icon":25,"path":26,"stem":27,"children":28,"page":22},"Guides","i-lucide-book-open","\u002Fguides","2.guides",[29,33,37,41,45,49,53,57],{"title":30,"path":31,"stem":32},"Connection & config","\u002Fguides\u002Fconnection","2.guides\u002F1.connection",{"title":34,"path":35,"stem":36},"Publish, RPC, history, presence","\u002Fguides\u002Foperations","2.guides\u002F2.operations",{"title":38,"path":39,"stem":40},"Events","\u002Fguides\u002Fevents","2.guides\u002F3.events",{"title":42,"path":43,"stem":44},"Subscriptions","\u002Fguides\u002Fsubscriptions","2.guides\u002F4.subscriptions",{"title":46,"path":47,"stem":48},"Tokens","\u002Fguides\u002Ftokens","2.guides\u002F5.tokens",{"title":50,"path":51,"stem":52},"Payloads (base64 vs rawJson)","\u002Fguides\u002Fpayloads","2.guides\u002F6.payloads",{"title":54,"path":55,"stem":56},"Rust backend","\u002Fguides\u002Frust","2.guides\u002F7.rust",{"title":58,"path":59,"stem":60},"Permissions","\u002Fguides\u002Fpermissions","2.guides\u002F8.permissions",{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":22},"API reference","i-lucide-file-code","\u002Freference","3.reference",[67,71,75,79],{"title":68,"path":69,"stem":70},"JavaScript API","\u002Freference\u002Fjavascript-api","3.reference\u002F1.javascript-api",{"title":72,"path":73,"stem":74},"Types","\u002Freference\u002Ftypes","3.reference\u002F2.types",{"title":76,"path":77,"stem":78},"Tauri commands","\u002Freference\u002Fcommands","3.reference\u002F3.commands",{"title":58,"path":80,"stem":81},"\u002Freference\u002Fpermissions","3.reference\u002F4.permissions",{"title":83,"icon":84,"path":85,"stem":86,"children":87,"page":22},"Platforms","i-lucide-monitor-smartphone","\u002Fplatforms","4.platforms",[88,92,96,100,104],{"title":89,"path":90,"stem":91},"Overview","\u002Fplatforms\u002Foverview","4.platforms\u002F1.overview",{"title":93,"path":94,"stem":95},"Desktop","\u002Fplatforms\u002Fdesktop","4.platforms\u002F2.desktop",{"title":97,"path":98,"stem":99},"Android","\u002Fplatforms\u002Fandroid","4.platforms\u002F3.android",{"title":101,"path":102,"stem":103},"iOS","\u002Fplatforms\u002Fios","4.platforms\u002F4.ios",{"title":105,"path":106,"stem":107},"Centrifugo server","\u002Fplatforms\u002Fserver","4.platforms\u002F5.server",{"title":109,"path":110,"stem":111},"Deprecations","\u002Fdeprecations","5.deprecations",{"title":113,"path":114,"stem":115},"Changelog","\u002Fchangelog","9.changelog",{"id":117,"title":46,"body":118,"description":881,"extension":882,"generated":22,"links":883,"meta":884,"navigation":283,"path":47,"seo":885,"stem":48,"__hash__":886},"docs\u002F2.guides\u002F5.tokens.md",{"type":119,"value":120,"toc":874},"minimark",[121,125,130,133,210,222,501,512,517,584,594,598,604,816,846,850,857,870],[122,123,124],"p",{},"Centrifugo authenticates a connection with a JWT and a private channel with a subscription JWT.\nYour backend signs them; the plugin passes them on and asks the frontend for new ones when needed.",[126,127,129],"h2",{"id":128},"connection-token","Connection token",[122,131,132],{},"Two ways to give the first token:",[134,135,136,156],"table",{},[137,138,139],"thead",{},[140,141,142,145,151],"tr",{},[143,144],"th",{},[143,146,147],{},[148,149,150],"code",{},"token: \"\u003Cjwt>\"",[143,152,153],{},[148,154,155],{},"requestToken: true",[157,158,159,183,196],"tbody",{},[140,160,161,165,172],{},[162,163,164],"td",{},"First connect",[162,166,167,168,171],{},"Uses ",[148,169,170],{},"token"," at once.",[162,173,174,175,178,179,182],{},"Emits ",[148,176,177],{},"need_token"," and waits for ",[148,180,181],{},"provideToken",".",[140,184,185,188,192],{},[162,186,187],{},"Before the token expires",[162,189,174,190,182],{},[148,191,177],{},[162,193,174,194,182],{},[148,195,177],{},[140,197,198,201,207],{},[162,199,200],{},"Neither set",[162,202,203,204,206],{},"Anonymous connection, ",[148,205,177],{}," never comes.",[162,208,209],{},"—",[122,211,212,213,215,216,218,219,221],{},"The ",[148,214,177],{}," handler is installed only when ",[148,217,170],{}," is set or ",[148,220,155],{},", so\nanonymous connections never wait for the frontend.",[223,224,229],"pre",{"className":225,"code":226,"language":227,"meta":228,"style":228},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { connect, onNeedToken, provideToken } from \"tauri-plugin-centrifugo-api\";\n\nawait onNeedToken(async () => {\n  try {\n    const token = await fetch(\"\u002Fapi\u002Fcentrifugo\u002Ftoken\").then((r) => r.text());\n    await provideToken(token);\n  } catch {\n    await provideToken(\"\"); \u002F\u002F see below\n  }\n});\n\nawait connect({ url, channels: [], useProtobuf: false, requestToken: true });\n","ts","",[148,230,231,278,285,310,318,379,395,406,427,433,443,448],{"__ignoreMap":228},[232,233,236,240,244,248,251,254,256,259,262,265,268,272,275],"span",{"class":234,"line":235},"line",1,[232,237,239],{"class":238},"s7zQu","import",[232,241,243],{"class":242},"sMK4o"," {",[232,245,247],{"class":246},"sTEyZ"," connect",[232,249,250],{"class":242},",",[232,252,253],{"class":246}," onNeedToken",[232,255,250],{"class":242},[232,257,258],{"class":246}," provideToken",[232,260,261],{"class":242}," }",[232,263,264],{"class":238}," from",[232,266,267],{"class":242}," \"",[232,269,271],{"class":270},"sfazB","tauri-plugin-centrifugo-api",[232,273,274],{"class":242},"\"",[232,276,277],{"class":242},";\n",[232,279,281],{"class":234,"line":280},2,[232,282,284],{"emptyLinePlaceholder":283},true,"\n",[232,286,288,291,294,297,301,304,307],{"class":234,"line":287},3,[232,289,290],{"class":238},"await",[232,292,253],{"class":293},"s2Zo4",[232,295,296],{"class":246},"(",[232,298,300],{"class":299},"spNyl","async",[232,302,303],{"class":242}," ()",[232,305,306],{"class":299}," =>",[232,308,309],{"class":242}," {\n",[232,311,313,316],{"class":234,"line":312},4,[232,314,315],{"class":238},"  try",[232,317,309],{"class":242},[232,319,321,324,327,330,333,336,339,341,344,346,349,351,354,356,358,362,364,366,369,371,374,377],{"class":234,"line":320},5,[232,322,323],{"class":299},"    const",[232,325,326],{"class":246}," token",[232,328,329],{"class":242}," =",[232,331,332],{"class":238}," await",[232,334,335],{"class":293}," fetch",[232,337,296],{"class":338},"swJcz",[232,340,274],{"class":242},[232,342,343],{"class":270},"\u002Fapi\u002Fcentrifugo\u002Ftoken",[232,345,274],{"class":242},[232,347,348],{"class":338},")",[232,350,182],{"class":242},[232,352,353],{"class":293},"then",[232,355,296],{"class":338},[232,357,296],{"class":242},[232,359,361],{"class":360},"sHdIc","r",[232,363,348],{"class":242},[232,365,306],{"class":299},[232,367,368],{"class":246}," r",[232,370,182],{"class":242},[232,372,373],{"class":293},"text",[232,375,376],{"class":338},"())",[232,378,277],{"class":242},[232,380,382,385,387,389,391,393],{"class":234,"line":381},6,[232,383,384],{"class":238},"    await",[232,386,258],{"class":293},[232,388,296],{"class":338},[232,390,170],{"class":246},[232,392,348],{"class":338},[232,394,277],{"class":242},[232,396,398,401,404],{"class":234,"line":397},7,[232,399,400],{"class":242},"  }",[232,402,403],{"class":238}," catch",[232,405,309],{"class":242},[232,407,409,411,413,415,418,420,423],{"class":234,"line":408},8,[232,410,384],{"class":238},[232,412,258],{"class":293},[232,414,296],{"class":338},[232,416,417],{"class":242},"\"\"",[232,419,348],{"class":338},[232,421,422],{"class":242},";",[232,424,426],{"class":425},"sHwdD"," \u002F\u002F see below\n",[232,428,430],{"class":234,"line":429},9,[232,431,432],{"class":242},"  }\n",[232,434,436,439,441],{"class":234,"line":435},10,[232,437,438],{"class":242},"}",[232,440,348],{"class":246},[232,442,277],{"class":242},[232,444,446],{"class":234,"line":445},11,[232,447,284],{"emptyLinePlaceholder":283},[232,449,451,453,455,457,460,463,465,468,471,474,476,479,481,485,487,490,492,495,497,499],{"class":234,"line":450},12,[232,452,290],{"class":238},[232,454,247],{"class":293},[232,456,296],{"class":246},[232,458,459],{"class":242},"{",[232,461,462],{"class":246}," url",[232,464,250],{"class":242},[232,466,467],{"class":338}," channels",[232,469,470],{"class":242},":",[232,472,473],{"class":246}," []",[232,475,250],{"class":242},[232,477,478],{"class":338}," useProtobuf",[232,480,470],{"class":242},[232,482,484],{"class":483},"sfNiH"," false",[232,486,250],{"class":242},[232,488,489],{"class":338}," requestToken",[232,491,470],{"class":242},[232,493,494],{"class":483}," true",[232,496,261],{"class":242},[232,498,348],{"class":246},[232,500,277],{"class":242},[122,502,503,504,507,508,511],{},"Register the listener before ",[148,505,506],{},"connect()",". There is no timeout: the SDK waits for the answer as\ncentrifuge-js does, and ",[148,509,510],{},"disconnect()"," ends the wait. A newer request replaces an older unanswered\none; the old one is retried, not treated as unauthorized.",[513,514,516],"h3",{"id":515},"what-to-answer","What to answer",[134,518,519,529],{},[137,520,521],{},[140,522,523,526],{},[143,524,525],{},"Call",[143,527,528],{},"Effect",[157,530,531,544,562,574],{},[140,532,533,538],{},[162,534,535],{},[148,536,537],{},"provideToken(token)",[162,539,540,541,543],{},"Answers the pending ",[148,542,177],{},". Rejects when none is pending.",[140,545,546,551],{},[162,547,548],{},[148,549,550],{},"provideToken(\"\")",[162,552,553,554,557,558,561],{},"\"No token\": an anonymous connect on the first connect; on a refresh the server disconnects the client as unauthorized (",[148,555,556],{},"disconnected",", code ",[148,559,560],{},"1",").",[140,563,564,569],{},[162,565,566],{},[148,567,568],{},"refresh({ token })",[162,570,540,571,573],{},[148,572,177],{},"; when none is pending, sets the token for the next connect.",[140,575,576,581],{},[162,577,578],{},[148,579,580],{},"setToken(token)",[162,582,583],{},"Replaces the token used from the next connect attempt; does not answer a request.",[122,585,586,587,590,591,593],{},"All of them reject with ",[148,588,589],{},"NotConnected"," when there is no client (",[148,592,181],{}," with \"no token\nrequest in progress\").",[126,595,597],{"id":596},"subscription-tokens","Subscription tokens",[122,599,600,601,603],{},"A subscription created with ",[148,602,170],{}," refreshes it the same way, per channel:",[223,605,607],{"className":225,"code":606,"language":227,"meta":228,"style":228},"import { addSubscriptionWithOptions, onNeedSubToken, subRefresh } from \"tauri-plugin-centrifugo-api\";\n\nawait onNeedSubToken(async ({ payload }) => {\n  const token = await fetch(`\u002Fapi\u002Fcentrifugo\u002Fsub-token?channel=${encodeURIComponent(payload.channel)}`)\n    .then((r) => r.text());\n  await subRefresh({ channel: payload.channel, token });\n});\n\nawait addSubscriptionWithOptions({ channel: \"$private:42\", token: firstToken });\n",[148,608,609,640,644,667,708,735,768,776,780],{"__ignoreMap":228},[232,610,611,613,615,618,620,623,625,628,630,632,634,636,638],{"class":234,"line":235},[232,612,239],{"class":238},[232,614,243],{"class":242},[232,616,617],{"class":246}," addSubscriptionWithOptions",[232,619,250],{"class":242},[232,621,622],{"class":246}," onNeedSubToken",[232,624,250],{"class":242},[232,626,627],{"class":246}," subRefresh",[232,629,261],{"class":242},[232,631,264],{"class":238},[232,633,267],{"class":242},[232,635,271],{"class":270},[232,637,274],{"class":242},[232,639,277],{"class":242},[232,641,642],{"class":234,"line":280},[232,643,284],{"emptyLinePlaceholder":283},[232,645,646,648,650,652,654,657,660,663,665],{"class":234,"line":287},[232,647,290],{"class":238},[232,649,622],{"class":293},[232,651,296],{"class":246},[232,653,300],{"class":299},[232,655,656],{"class":242}," ({",[232,658,659],{"class":360}," payload",[232,661,662],{"class":242}," })",[232,664,306],{"class":299},[232,666,309],{"class":242},[232,668,669,672,674,676,678,680,682,685,688,691,694,697,699,702,705],{"class":234,"line":312},[232,670,671],{"class":299},"  const",[232,673,326],{"class":246},[232,675,329],{"class":242},[232,677,332],{"class":238},[232,679,335],{"class":293},[232,681,296],{"class":338},[232,683,684],{"class":242},"`",[232,686,687],{"class":270},"\u002Fapi\u002Fcentrifugo\u002Fsub-token?channel=",[232,689,690],{"class":242},"${",[232,692,693],{"class":293},"encodeURIComponent",[232,695,696],{"class":246},"(payload",[232,698,182],{"class":242},[232,700,701],{"class":246},"channel)",[232,703,704],{"class":242},"}`",[232,706,707],{"class":338},")\n",[232,709,710,713,715,717,719,721,723,725,727,729,731,733],{"class":234,"line":320},[232,711,712],{"class":242},"    .",[232,714,353],{"class":293},[232,716,296],{"class":338},[232,718,296],{"class":242},[232,720,361],{"class":360},[232,722,348],{"class":242},[232,724,306],{"class":299},[232,726,368],{"class":246},[232,728,182],{"class":242},[232,730,373],{"class":293},[232,732,376],{"class":338},[232,734,277],{"class":242},[232,736,737,740,742,744,746,749,751,753,755,758,760,762,764,766],{"class":234,"line":381},[232,738,739],{"class":238},"  await",[232,741,627],{"class":293},[232,743,296],{"class":338},[232,745,459],{"class":242},[232,747,748],{"class":338}," channel",[232,750,470],{"class":242},[232,752,659],{"class":246},[232,754,182],{"class":242},[232,756,757],{"class":246},"channel",[232,759,250],{"class":242},[232,761,326],{"class":246},[232,763,261],{"class":242},[232,765,348],{"class":338},[232,767,277],{"class":242},[232,769,770,772,774],{"class":234,"line":397},[232,771,438],{"class":242},[232,773,348],{"class":246},[232,775,277],{"class":242},[232,777,778],{"class":234,"line":408},[232,779,284],{"emptyLinePlaceholder":283},[232,781,782,784,786,788,790,792,794,796,799,801,803,805,807,810,812,814],{"class":234,"line":429},[232,783,290],{"class":238},[232,785,617],{"class":293},[232,787,296],{"class":246},[232,789,459],{"class":242},[232,791,748],{"class":338},[232,793,470],{"class":242},[232,795,267],{"class":242},[232,797,798],{"class":270},"$private:42",[232,800,274],{"class":242},[232,802,250],{"class":242},[232,804,326],{"class":338},[232,806,470],{"class":242},[232,808,809],{"class":246}," firstToken ",[232,811,438],{"class":242},[232,813,348],{"class":246},[232,815,277],{"class":242},[122,817,818,821,822,824,825,827,828,831,832,835,836,838,839,842,843,182],{},[148,819,820],{},"need_sub_token"," carries ",[148,823,757],{}," and ",[148,826,227],{},". ",[148,829,830],{},"subRefresh"," rejects when no request is pending for\nthat channel. An empty token means unauthorized: the subscription ends with ",[148,833,834],{},"unsubscribed",".\nSubscriptions without ",[148,837,170],{}," (including those from ",[148,840,841],{},"channels",") never ask; channels that need a\ntoken must be added with ",[148,844,845],{},"addSubscriptionWithOptions",[126,847,849],{"id":848},"expiry-and-refresh","Expiry and refresh",[122,851,852,853,856],{},"The SDK reads the ",[148,854,855],{},"ttl"," the server returns for the token and asks for a new one shortly before\nit expires; there is nothing to schedule in the app. If the token has already expired on\nconnect, the server answers with \"token expired\" and the SDK asks again.",[122,858,859,860,863,864,867,868,182],{},"Signing tokens is your backend's job, for example with the HMAC secret\n(",[148,861,862],{},"token_hmac_secret_key"," in Centrifugo v5) and the ",[148,865,866],{},"sub"," claim for the user ID; for subscription\ntokens also ",[148,869,757],{},[871,872,873],"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .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 .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 pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}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);}",{"title":228,"searchDepth":280,"depth":287,"links":875},[876,879,880],{"id":128,"depth":280,"text":129,"children":877},[878],{"id":515,"depth":287,"text":516},{"id":596,"depth":280,"text":597},{"id":848,"depth":280,"text":849},"Connection and subscription JWTs - token vs requestToken, need_token \u002F provideToken, need_sub_token \u002F subRefresh.","md",null,{},{"title":46,"description":881},"h2i4-x357gPpdb7ucTRHKfTvUwmQhBXAK20Lt7ZDcGo",[888,890],{"title":42,"path":43,"stem":44,"description":889,"children":-1},"Client-side subscriptions with options - recovery, resume from a position, delta compression, join\u002Fleave.",{"title":50,"path":51,"stem":52,"description":891,"children":-1},"How data crosses the Tauri bridge - base64 by default, raw JSON as an option.",1794166800622]