[{"data":1,"prerenderedAt":1010},["ShallowReactive",2],{"navigation":3,"/sanctum/2fa":51,"/sanctum/2fa-surround":1005},[4,18,43],{"title":5,"path":6,"stem":7,"children":8,"icon":17},"Getting Started","/getting-started","1.getting-started/1.index",[9,12],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-simple-icons-laravel",{"title":13,"path":14,"stem":15,"icon":16},"Installation","/getting-started/installation","1.getting-started/2.installation","i-lucide-download",false,{"title":19,"path":20,"stem":21,"children":22,"page":17},"Sanctum","/sanctum","2.sanctum",[23,28,33,38],{"title":24,"path":25,"stem":26,"icon":27},"Configuration","/sanctum/configuration","2.sanctum/1.configuration","i-lucide-cog",{"title":29,"path":30,"stem":31,"icon":32},"Cookie Authentication","/sanctum/cookie","2.sanctum/2.cookie","i-lucide-cookie",{"title":34,"path":35,"stem":36,"icon":37},"Sanctum 2FA Flow","/sanctum/2fa","2.sanctum/3.2fa","i-lucide-shield-check",{"title":39,"path":40,"stem":41,"icon":42},"Server Proxy","/sanctum/proxy","2.sanctum/4.proxy","i-lucide-waypoints",{"title":44,"path":45,"stem":46,"children":47,"page":17},"Passport","/passport","3.passport",[48],{"title":24,"path":49,"stem":50,"icon":27},"/passport/configuration","3.passport/1.configuration",{"id":52,"title":34,"body":53,"description":998,"extension":999,"links":1000,"meta":1001,"navigation":1002,"path":35,"seo":1003,"stem":36,"__hash__":1004},"docs/2.sanctum/3.2fa.md",{"type":54,"value":55,"toc":983},"minimark",[56,65,77,80,83,88,98,105,134,144,146,151,158,164,168,171,332,336,339,342,398,401,405,409,412,443,446,450,453,474,478,481,543,547,564,568,571,920,923,927,938,942,945,979],[57,58,59,60,64],"p",{},"In ",[61,62,63],"strong",{},"Nuxt Umbu",", Two-Factor Authentication (2FA) is completely optional.",[57,66,67,68,72,73,76],{},"It is only enabled when the ",[69,70,71],"code",{},"2fa"," endpoint is configured within the selected strategy.",[74,75],"br",{},"\nIf this endpoint is not defined — or is removed — 2FA support is automatically disabled automatically, without affecting the standard authentication flow.",[57,78,79],{},"This provides full flexibility, allowing you to use standard Sanctum authentication or enable 2FA only when needed.",[81,82],"hr",{},[84,85,87],"h2",{"id":86},"how-2fa-works-with-sanctum","How 2FA Works with Sanctum",[57,89,90,91,94,95,97],{},"Below is the complete and correct 2FA flow for the ",[61,92,93],{},"Sanctum provider"," in ",[61,96,63],{},", including optional middleware usage and SSR behavior.",[57,99,100,101,104],{},"Unlike the Passport strategy, ",[61,102,103],{},"Sanctum does NOT require a custom 2FA header",", because authentication is session-based and Laravel already knows the authenticated user through the session cookie.",[106,107,108,111],"warning",{},[57,109,110],{},"This means:",[112,113,114,122,128,131],"ul",{},[115,116,117,118,121],"li",{},"No ",[69,119,120],{},"Authorization: Bearer"," header",[115,123,124,125,121],{},"No custom ",[69,126,127],{},"X-2FA",[115,129,130],{},"Laravel session handles user state",[115,132,133],{},"CSRF protection is handled automatically",[57,135,136,137],{},"Official Laravel documentation:",[138,139,143],"a",{"href":140,"rel":141},"https://laravel.com/docs/12.x/sanctum",[142],"nofollow","Laravel Sanctum",[81,145],{},[147,148,150],"h3",{"id":149},"_1-user-logs-in-normally","1. User Logs In Normally",[57,152,153,154,157],{},"Authentication works through ",[61,155,156],{},"Laravel session cookies"," (Sanctum).",[57,159,160,161],{},"The user logs in using: ",[69,162,163],{},"POST /login",[147,165,167],{"id":166},"_2-frontend-sends-the-2fa-code","2. Frontend Sends the 2FA Code",[57,169,170],{},"Example:",[172,173,178],"pre",{"className":174,"code":175,"language":176,"meta":177,"style":177},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const { $auth } = useNuxtApp()\n\nconst handleVerify = async () => {\n    try {\n        await $auth._2fa('admin', code)\n        // success\n    } catch (err) {\n        // error\n    }\n}\n","typescript","",[69,179,180,210,217,240,249,286,293,314,320,326],{"__ignoreMap":177},[181,182,185,189,193,197,200,203,207],"span",{"class":183,"line":184},"line",1,[181,186,188],{"class":187},"spNyl","const",[181,190,192],{"class":191},"sMK4o"," {",[181,194,196],{"class":195},"sTEyZ"," $auth ",[181,198,199],{"class":191},"}",[181,201,202],{"class":191}," =",[181,204,206],{"class":205},"s2Zo4"," useNuxtApp",[181,208,209],{"class":195},"()\n",[181,211,213],{"class":183,"line":212},2,[181,214,216],{"emptyLinePlaceholder":215},true,"\n",[181,218,220,222,225,228,231,234,237],{"class":183,"line":219},3,[181,221,188],{"class":187},[181,223,224],{"class":195}," handleVerify ",[181,226,227],{"class":191},"=",[181,229,230],{"class":187}," async",[181,232,233],{"class":191}," ()",[181,235,236],{"class":187}," =>",[181,238,239],{"class":191}," {\n",[181,241,243,247],{"class":183,"line":242},4,[181,244,246],{"class":245},"s7zQu","    try",[181,248,239],{"class":191},[181,250,252,255,258,261,264,268,271,275,277,280,283],{"class":183,"line":251},5,[181,253,254],{"class":245},"        await",[181,256,257],{"class":195}," $auth",[181,259,260],{"class":191},".",[181,262,263],{"class":205},"_2fa",[181,265,267],{"class":266},"swJcz","(",[181,269,270],{"class":191},"'",[181,272,274],{"class":273},"sfazB","admin",[181,276,270],{"class":191},[181,278,279],{"class":191},",",[181,281,282],{"class":195}," code",[181,284,285],{"class":266},")\n",[181,287,289],{"class":183,"line":288},6,[181,290,292],{"class":291},"sHwdD","        // success\n",[181,294,296,299,302,305,308,311],{"class":183,"line":295},7,[181,297,298],{"class":191},"    }",[181,300,301],{"class":245}," catch",[181,303,304],{"class":266}," (",[181,306,307],{"class":195},"err",[181,309,310],{"class":266},") ",[181,312,313],{"class":191},"{\n",[181,315,317],{"class":183,"line":316},8,[181,318,319],{"class":291},"        // error\n",[181,321,323],{"class":183,"line":322},9,[181,324,325],{"class":191},"    }\n",[181,327,329],{"class":183,"line":328},10,[181,330,331],{"class":191},"}\n",[147,333,335],{"id":334},"_3-backend-validates-the-code","3. Backend validates the code",[57,337,338],{},"Your Laravel backend must validate the code using the current session user.",[57,340,341],{},"If valid, it MUST return:",[172,343,347],{"className":344,"code":345,"language":346,"meta":177,"style":177},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","    {\n    \"access_token\": \"temporary-2fa-token\",\n    \"expires_in\": 3600\n    }\n","json",[69,348,349,354,379,394],{"__ignoreMap":177},[181,350,351],{"class":183,"line":184},[181,352,353],{"class":191},"    {\n",[181,355,356,359,362,365,368,371,374,376],{"class":183,"line":212},[181,357,358],{"class":191},"    \"",[181,360,361],{"class":187},"access_token",[181,363,364],{"class":191},"\"",[181,366,367],{"class":191},":",[181,369,370],{"class":191}," \"",[181,372,373],{"class":273},"temporary-2fa-token",[181,375,364],{"class":191},[181,377,378],{"class":191},",\n",[181,380,381,383,386,388,390],{"class":183,"line":219},[181,382,358],{"class":191},[181,384,385],{"class":187},"expires_in",[181,387,364],{"class":191},[181,389,367],{"class":191},[181,391,393],{"class":392},"sbssI"," 3600\n",[181,395,396],{"class":183,"line":242},[181,397,325],{"class":191},[57,399,400],{},"If the response does not contain both:",[57,402,403],{},[69,404,361],{},[57,406,407],{},[69,408,385],{},[57,410,411],{},"Nuxt Umbu will throw:",[172,413,415],{"className":174,"code":414,"language":176,"meta":177,"style":177},"    throw new Error('Invalid 2FA response');\n",[69,416,417],{"__ignoreMap":177},[181,418,419,422,425,428,430,432,435,437,440],{"class":183,"line":184},[181,420,421],{"class":245},"    throw",[181,423,424],{"class":191}," new",[181,426,427],{"class":205}," Error",[181,429,267],{"class":195},[181,431,270],{"class":191},[181,433,434],{"class":273},"Invalid 2FA response",[181,436,270],{"class":191},[181,438,439],{"class":195},")",[181,441,442],{"class":191},";\n",[57,444,445],{},"Without this structure, 2FA will not work.",[147,447,449],{"id":448},"_4-nuxt-umbu-stores-the-token","4. Nuxt Umbu stores the token",[57,451,452],{},"On success:",[112,454,455,458,461,468,471],{},[115,456,457],{},"If SSR is being used:",[115,459,460],{},"Middleware also validates on the server",[115,462,463,464,467],{},"A cookie named ",[69,465,466],{},"token_2fa"," is checked",[115,469,470],{},"Currently the cookie name is fixed",[115,472,473],{},"Future versions will allow configuring the cookie name",[84,475,477],{"id":476},"_2fa-middleware-optional","2FA Middleware (Optional)",[57,479,480],{},"To protect pages with 2FA:",[172,482,484],{"className":174,"code":483,"language":176,"meta":177,"style":177},"definePageMeta({\n  layout: false,\n  middleware: ['auth', '_2fa']\n})\n",[69,485,486,495,508,537],{"__ignoreMap":177},[181,487,488,491,493],{"class":183,"line":184},[181,489,490],{"class":205},"definePageMeta",[181,492,267],{"class":195},[181,494,313],{"class":191},[181,496,497,500,502,506],{"class":183,"line":212},[181,498,499],{"class":266},"  layout",[181,501,367],{"class":191},[181,503,505],{"class":504},"sfNiH"," false",[181,507,378],{"class":191},[181,509,510,513,515,518,520,523,525,527,530,532,534],{"class":183,"line":219},[181,511,512],{"class":266},"  middleware",[181,514,367],{"class":191},[181,516,517],{"class":195}," [",[181,519,270],{"class":191},[181,521,522],{"class":273},"auth",[181,524,270],{"class":191},[181,526,279],{"class":191},[181,528,529],{"class":191}," '",[181,531,263],{"class":273},[181,533,270],{"class":191},[181,535,536],{"class":195},"]\n",[181,538,539,541],{"class":183,"line":242},[181,540,199],{"class":191},[181,542,285],{"class":195},[147,544,546],{"id":545},"important","Important:",[112,548,549,552,555,558,561],{},[115,550,551],{},"auth middleware validates login",[115,553,554],{},"_2fa middleware validates 2FA completion",[115,556,557],{},"Using _2fa is NOT mandatory",[115,559,560],{},"Only required if you want to enforce 2FA protection",[115,562,563],{},"If you do not use _2fa, 2FA will not block access.",[84,565,567],{"id":566},"enabling-disabling-2fa","Enabling / Disabling 2FA",[57,569,570],{},"2FA is enabled only if the endpoint is defined:",[172,572,575],{"className":174,"code":573,"filename":574,"language":176,"meta":177,"style":177},"export default defineNuxtConfig({\n    auth: {\n        csrf: '/sanctum/csrf-cookie',\n        provider: 'sanctum',\n        strategies: {\n            client: {\n                redirect: {\n                    login: '/auth',\n                    logout: '/auth'\n                },\n                user: {\n                    property: 'profile'\n                },\n                endpoints: {\n                    login:  { url: '/login', method: 'post' },\n                    user:   { url: '/api/profile', method: 'get' },\n                    '2fa':  { url: '/api/token-2fa', method: 'post' }, // If present → 2FA enabled\n                    logout: { url: '/api/logout', method: 'post' }\n                }\n            }\n        }\n    },\n})\n","nuxt.config.ts",[69,576,577,592,601,617,633,642,651,660,676,690,695,705,720,725,735,774,811,854,889,895,901,907,913],{"__ignoreMap":177},[181,578,579,582,585,588,590],{"class":183,"line":184},[181,580,581],{"class":245},"export",[181,583,584],{"class":245}," default",[181,586,587],{"class":205}," defineNuxtConfig",[181,589,267],{"class":195},[181,591,313],{"class":191},[181,593,594,597,599],{"class":183,"line":212},[181,595,596],{"class":266},"    auth",[181,598,367],{"class":191},[181,600,239],{"class":191},[181,602,603,606,608,610,613,615],{"class":183,"line":219},[181,604,605],{"class":266},"        csrf",[181,607,367],{"class":191},[181,609,529],{"class":191},[181,611,612],{"class":273},"/sanctum/csrf-cookie",[181,614,270],{"class":191},[181,616,378],{"class":191},[181,618,619,622,624,626,629,631],{"class":183,"line":242},[181,620,621],{"class":266},"        provider",[181,623,367],{"class":191},[181,625,529],{"class":191},[181,627,628],{"class":273},"sanctum",[181,630,270],{"class":191},[181,632,378],{"class":191},[181,634,635,638,640],{"class":183,"line":251},[181,636,637],{"class":266},"        strategies",[181,639,367],{"class":191},[181,641,239],{"class":191},[181,643,644,647,649],{"class":183,"line":288},[181,645,646],{"class":266},"            client",[181,648,367],{"class":191},[181,650,239],{"class":191},[181,652,653,656,658],{"class":183,"line":295},[181,654,655],{"class":266},"                redirect",[181,657,367],{"class":191},[181,659,239],{"class":191},[181,661,662,665,667,669,672,674],{"class":183,"line":316},[181,663,664],{"class":266},"                    login",[181,666,367],{"class":191},[181,668,529],{"class":191},[181,670,671],{"class":273},"/auth",[181,673,270],{"class":191},[181,675,378],{"class":191},[181,677,678,681,683,685,687],{"class":183,"line":322},[181,679,680],{"class":266},"                    logout",[181,682,367],{"class":191},[181,684,529],{"class":191},[181,686,671],{"class":273},[181,688,689],{"class":191},"'\n",[181,691,692],{"class":183,"line":328},[181,693,694],{"class":191},"                },\n",[181,696,698,701,703],{"class":183,"line":697},11,[181,699,700],{"class":266},"                user",[181,702,367],{"class":191},[181,704,239],{"class":191},[181,706,708,711,713,715,718],{"class":183,"line":707},12,[181,709,710],{"class":266},"                    property",[181,712,367],{"class":191},[181,714,529],{"class":191},[181,716,717],{"class":273},"profile",[181,719,689],{"class":191},[181,721,723],{"class":183,"line":722},13,[181,724,694],{"class":191},[181,726,728,731,733],{"class":183,"line":727},14,[181,729,730],{"class":266},"                endpoints",[181,732,367],{"class":191},[181,734,239],{"class":191},[181,736,738,740,742,745,748,750,752,755,757,759,762,764,766,769,771],{"class":183,"line":737},15,[181,739,664],{"class":266},[181,741,367],{"class":191},[181,743,744],{"class":191},"  {",[181,746,747],{"class":266}," url",[181,749,367],{"class":191},[181,751,529],{"class":191},[181,753,754],{"class":273},"/login",[181,756,270],{"class":191},[181,758,279],{"class":191},[181,760,761],{"class":266}," method",[181,763,367],{"class":191},[181,765,529],{"class":191},[181,767,768],{"class":273},"post",[181,770,270],{"class":191},[181,772,773],{"class":191}," },\n",[181,775,777,780,782,785,787,789,791,794,796,798,800,802,804,807,809],{"class":183,"line":776},16,[181,778,779],{"class":266},"                    user",[181,781,367],{"class":191},[181,783,784],{"class":191},"   {",[181,786,747],{"class":266},[181,788,367],{"class":191},[181,790,529],{"class":191},[181,792,793],{"class":273},"/api/profile",[181,795,270],{"class":191},[181,797,279],{"class":191},[181,799,761],{"class":266},[181,801,367],{"class":191},[181,803,529],{"class":191},[181,805,806],{"class":273},"get",[181,808,270],{"class":191},[181,810,773],{"class":191},[181,812,814,817,819,821,823,825,827,829,831,834,836,838,840,842,844,846,848,851],{"class":183,"line":813},17,[181,815,816],{"class":191},"                    '",[181,818,71],{"class":266},[181,820,270],{"class":191},[181,822,367],{"class":191},[181,824,744],{"class":191},[181,826,747],{"class":266},[181,828,367],{"class":191},[181,830,529],{"class":191},[181,832,833],{"class":273},"/api/token-2fa",[181,835,270],{"class":191},[181,837,279],{"class":191},[181,839,761],{"class":266},[181,841,367],{"class":191},[181,843,529],{"class":191},[181,845,768],{"class":273},[181,847,270],{"class":191},[181,849,850],{"class":191}," },",[181,852,853],{"class":291}," // If present → 2FA enabled\n",[181,855,857,859,861,863,865,867,869,872,874,876,878,880,882,884,886],{"class":183,"line":856},18,[181,858,680],{"class":266},[181,860,367],{"class":191},[181,862,192],{"class":191},[181,864,747],{"class":266},[181,866,367],{"class":191},[181,868,529],{"class":191},[181,870,871],{"class":273},"/api/logout",[181,873,270],{"class":191},[181,875,279],{"class":191},[181,877,761],{"class":266},[181,879,367],{"class":191},[181,881,529],{"class":191},[181,883,768],{"class":273},[181,885,270],{"class":191},[181,887,888],{"class":191}," }\n",[181,890,892],{"class":183,"line":891},19,[181,893,894],{"class":191},"                }\n",[181,896,898],{"class":183,"line":897},20,[181,899,900],{"class":191},"            }\n",[181,902,904],{"class":183,"line":903},21,[181,905,906],{"class":191},"        }\n",[181,908,910],{"class":183,"line":909},22,[181,911,912],{"class":191},"    },\n",[181,914,916,918],{"class":183,"line":915},23,[181,917,199],{"class":191},[181,919,285],{"class":195},[57,921,922],{},"If you remove:",[147,924,926],{"id":925},"then","Then:",[112,928,929,932,935],{},[115,930,931],{},"_2fa() method should not be used",[115,933,934],{},"_2fa middleware should not be applied",[115,936,937],{},"System works as standard Sanctum authentication",[84,939,941],{"id":940},"server-side-validation-ssr","Server-Side Validation (SSR)",[57,943,944],{},"When using SSR:",[112,946,947,950,955,958,961,964,967,970,973,976],{},[115,948,949],{},"Middleware runs on server",[115,951,952,953],{},"Reads cookie ",[69,954,466],{},[115,956,957],{},"Validates active strategy",[115,959,960],{},"Validates session state",[115,962,963],{},"Forces logout if invalid",[115,965,966],{},"This ensures protection in:",[115,968,969],{},"CSR",[115,971,972],{},"SSR",[115,974,975],{},"Page refresh",[115,977,978],{},"Direct URL access",[980,981,982],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":177,"searchDepth":184,"depth":212,"links":984},[985,991,994,997],{"id":86,"depth":212,"text":87,"children":986},[987,988,989,990],{"id":149,"depth":219,"text":150},{"id":166,"depth":219,"text":167},{"id":334,"depth":219,"text":335},{"id":448,"depth":219,"text":449},{"id":476,"depth":212,"text":477,"children":992},[993],{"id":545,"depth":219,"text":546},{"id":566,"depth":212,"text":567,"children":995},[996],{"id":925,"depth":219,"text":926},{"id":940,"depth":212,"text":941},"Complete 2FA flow with optional middleware in Nuxt Umbu","md",null,{},{"icon":37},{"title":34,"description":998},"UlK_IJjp8C2u86QMvPdhqvNxGOc29glON6h1KL_2F2w",[1006,1008],{"title":29,"path":30,"stem":31,"description":1007,"icon":32,"children":-1},"Set up cookie CSRF authentication for Sanctum",{"title":39,"path":40,"stem":41,"description":1009,"icon":42,"children":-1},"Planned internal server proxy for Sanctum SSR support",1774883773199]