[{"data":1,"prerenderedAt":1857},["ShallowReactive",2],{"navigation":3,"\u002Fmiddleware\u002Ftwo-factor":170,"\u002Fmiddleware\u002Ftwo-factor-surround":1852},[4,18,43,75,103,120,134],{"title":5,"path":6,"stem":7,"children":8,"icon":17},"Getting Started","\u002Fgetting-started","1.getting-started\u002F1.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","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",false,{"title":19,"path":20,"stem":21,"children":22,"page":17},"Sanctum","\u002Fsanctum","2.sanctum",[23,28,33,38],{"title":24,"path":25,"stem":26,"icon":27},"Configuration","\u002Fsanctum\u002Fconfiguration","2.sanctum\u002F1.configuration","i-lucide-cog",{"title":29,"path":30,"stem":31,"icon":32},"Cookie Authentication","\u002Fsanctum\u002Fcookie","2.sanctum\u002F2.cookie","i-lucide-cookie",{"title":34,"path":35,"stem":36,"icon":37},"Sanctum 2FA Flow","\u002Fsanctum\u002Ftwo-factor","2.sanctum\u002F3.two-factor","i-lucide-shield-check",{"title":39,"path":40,"stem":41,"icon":42},"Server Proxy","\u002Fsanctum\u002Fproxy","2.sanctum\u002F4.proxy","i-lucide-waypoints",{"title":44,"path":45,"stem":46,"children":47,"page":17},"Passport","\u002Fpassport","3.passport",[48,51,56,61,66,70],{"title":24,"path":49,"stem":50,"icon":27},"\u002Fpassport\u002Fconfiguration","3.passport\u002F1.configuration",{"title":52,"path":53,"stem":54,"icon":55},"Login & Logout","\u002Fpassport\u002Flogin-logout","3.passport\u002F2.login-logout","i-lucide-log-in",{"title":57,"path":58,"stem":59,"icon":60},"Token Management","\u002Fpassport\u002Ftokens","3.passport\u002F3.tokens","i-lucide-key",{"title":62,"path":63,"stem":64,"icon":65},"Two-Factor Authentication","\u002Fpassport\u002Ftwo-factor","3.passport\u002F4.two-factor","i-lucide-shield",{"title":67,"path":68,"stem":69,"icon":37},"Middleware & Route Protection","\u002Fpassport\u002Fmiddleware","3.passport\u002F5.middleware",{"title":71,"path":72,"stem":73,"icon":74},"Examples & Use Cases","\u002Fpassport\u002Fexamples","3.passport\u002F6.examples","i-lucide-code",{"title":76,"path":77,"stem":78,"children":79,"page":17},"Composables","\u002Fcomposables","4.composables",[80,84,89,94,99],{"title":76,"path":81,"stem":82,"icon":83},"\u002Fcomposables\u002Fcomposables","4.composables\u002F1.composables","i-lucide-code-2",{"title":85,"path":86,"stem":87,"icon":88},"$autx","\u002Fcomposables\u002Fautx","4.composables\u002F2.autx","i-lucide-globe",{"title":90,"path":91,"stem":92,"icon":93},"useAuthConfig","\u002Fcomposables\u002Fuse-auth-config","4.composables\u002F3.use-auth-config","i-lucide-settings",{"title":95,"path":96,"stem":97,"icon":98},"useAuthStore","\u002Fcomposables\u002Fuse-auth-store","4.composables\u002F4.use-auth-store","i-lucide-database",{"title":100,"path":101,"stem":102,"icon":37},"useEnsureCsrf","\u002Fcomposables\u002Fuse-ensure-csrf","4.composables\u002F5.use-ensure-csrf",{"title":104,"path":105,"stem":106,"children":107,"page":17},"Middleware","\u002Fmiddleware","5.middleware",[108,111,116],{"title":104,"path":109,"stem":110,"icon":37},"\u002Fmiddleware\u002Fmiddleware","5.middleware\u002F1.middleware",{"title":112,"path":113,"stem":114,"icon":115},"auth","\u002Fmiddleware\u002Fauth","5.middleware\u002F2.auth","i-lucide-lock",{"title":117,"path":118,"stem":119,"icon":65},"two-factor","\u002Fmiddleware\u002Ftwo-factor","5.middleware\u002F3.two-factor",{"title":121,"path":122,"stem":123,"children":124,"page":17},"Hooks","\u002Fhooks","6.hooks",[125,129],{"title":121,"path":126,"stem":127,"icon":128},"\u002Fhooks\u002Fhooks","6.hooks\u002F1.hooks","i-lucide-webhook",{"title":130,"path":131,"stem":132,"icon":133},"prepare:types","\u002Fhooks\u002Fprepare-types","6.hooks\u002F2.prepare-types","i-lucide-file-code",{"title":135,"path":136,"stem":137,"children":138,"page":17},"Advanced","\u002Fadvanced","7.advanced",[139,143,148,152,156,161,165],{"title":135,"path":140,"stem":141,"icon":142},"\u002Fadvanced\u002Fadvanced","7.advanced\u002F1.advanced","i-lucide-settings-2",{"title":144,"path":145,"stem":146,"icon":147},"Custom Configuration","\u002Fadvanced\u002Fcustom-configuration","7.advanced\u002F2.custom-configuration","i-lucide-sliders",{"title":149,"path":150,"stem":151,"icon":32},"Cookie Configuration","\u002Fadvanced\u002Fcookie-configuration","7.advanced\u002F3.cookie-configuration",{"title":153,"path":154,"stem":155,"icon":133},"TypeScript Integration","\u002Fadvanced\u002Ftypescript-integration","7.advanced\u002F4.typescript-integration",{"title":157,"path":158,"stem":159,"icon":160},"Module Aliases","\u002Fadvanced\u002Fmodule-aliases","7.advanced\u002F5.module-aliases","i-lucide-square-library",{"title":162,"path":163,"stem":164,"icon":37},"Security Features","\u002Fadvanced\u002Fsecurity-features","7.advanced\u002F6.security-features",{"title":166,"path":167,"stem":168,"icon":169},"Runtime Configuration","\u002Fadvanced\u002Fruntime-configuration","7.advanced\u002F7.runtime-configuration","i-lucide-server",{"id":171,"title":117,"body":172,"description":1845,"extension":1846,"links":1847,"meta":1848,"navigation":1849,"path":118,"seo":1850,"stem":119,"__hash__":1851},"docs\u002F5.middleware\u002F3.two-factor.md",{"type":173,"value":174,"toc":1810},"minimark",[175,183,188,191,196,201,204,220,224,227,238,242,246,313,317,368,372,443,446,450,454,457,469,473,476,491,495,499,844,848,1078,1082,1086,1106,1110,1124,1128,1131,1142,1145,1269,1273,1277,1408,1412,1536,1540,1604,1607,1611,1614,1637,1641,1645,1648,1665,1669,1672,1759,1763,1777,1781,1806],[176,177,178,179,182],"p",{},"The ",[180,181,117],"code",{}," middleware protects routes that require two-factor authentication (2FA). It validates that the user has completed the 2FA verification process before allowing access to protected routes.",[184,185,187],"h2",{"id":186},"overview","Overview",[176,189,190],{},"The two-factor middleware is similar to the auth middleware but specifically validates 2FA tokens. It ensures that users who have 2FA enabled on their account have completed the second factor authentication.",[192,193,195],"h3",{"id":194},"provider-specific-behavior","Provider-Specific Behavior",[197,198,200],"h4",{"id":199},"sanctum-provider","Sanctum Provider",[176,202,203],{},"For Sanctum, the two-factor middleware:",[205,206,207,211,214,217],"ul",{},[208,209,210],"li",{},"Validates the 2FA cookie token",[208,212,213],{},"Checks token expiration",[208,215,216],{},"Validates strategy consistency",[208,218,219],{},"Handles server-side and client-side validation differently",[197,221,223],{"id":222},"passport-provider","Passport Provider",[176,225,226],{},"For Passport, the two-factor middleware:",[205,228,229,232,234,236],{},[208,230,231],{},"Validates the 2FA access token",[208,233,213],{},[208,235,216],{},[208,237,219],{},[184,239,241],{"id":240},"usage","Usage",[192,243,245],{"id":244},"basic-usage","Basic Usage",[247,248,253],"pre",{"className":249,"code":250,"language":251,"meta":252,"style":252},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F pages\u002Fsettings\u002Fsecurity.vue\ndefinePageMeta({\n  middleware: ['umbu:two-factor']\n})\n","typescript","",[180,254,255,264,279,304],{"__ignoreMap":252},[256,257,260],"span",{"class":258,"line":259},"line",1,[256,261,263],{"class":262},"sHwdD","\u002F\u002F pages\u002Fsettings\u002Fsecurity.vue\n",[256,265,267,271,275],{"class":258,"line":266},2,[256,268,270],{"class":269},"s2Zo4","definePageMeta",[256,272,274],{"class":273},"sTEyZ","(",[256,276,278],{"class":277},"sMK4o","{\n",[256,280,282,286,289,292,295,299,301],{"class":258,"line":281},3,[256,283,285],{"class":284},"swJcz","  middleware",[256,287,288],{"class":277},":",[256,290,291],{"class":273}," [",[256,293,294],{"class":277},"'",[256,296,298],{"class":297},"sfazB","umbu:two-factor",[256,300,294],{"class":277},[256,302,303],{"class":273},"]\n",[256,305,307,310],{"class":258,"line":306},4,[256,308,309],{"class":277},"}",[256,311,312],{"class":273},")\n",[192,314,316],{"id":315},"combined-with-auth-middleware","Combined with Auth Middleware",[247,318,320],{"className":249,"code":319,"language":251,"meta":252,"style":252},"\u002F\u002F pages\u002Fadmin\u002Findex.vue\ndefinePageMeta({\n  middleware: ['umbu:auth', 'umbu:two-factor']\n})\n",[180,321,322,327,335,362],{"__ignoreMap":252},[256,323,324],{"class":258,"line":259},[256,325,326],{"class":262},"\u002F\u002F pages\u002Fadmin\u002Findex.vue\n",[256,328,329,331,333],{"class":258,"line":266},[256,330,270],{"class":269},[256,332,274],{"class":273},[256,334,278],{"class":277},[256,336,337,339,341,343,345,348,350,353,356,358,360],{"class":258,"line":281},[256,338,285],{"class":284},[256,340,288],{"class":277},[256,342,291],{"class":273},[256,344,294],{"class":277},[256,346,347],{"class":297},"umbu:auth",[256,349,294],{"class":277},[256,351,352],{"class":277},",",[256,354,355],{"class":277}," '",[256,357,298],{"class":297},[256,359,294],{"class":277},[256,361,303],{"class":273},[256,363,364,366],{"class":258,"line":306},[256,365,309],{"class":277},[256,367,312],{"class":273},[192,369,371],{"id":370},"conditional-2fa","Conditional 2FA",[247,373,375],{"className":249,"code":374,"language":251,"meta":252,"style":252},"\u002F\u002F pages\u002Fsensitive-operation.vue\n\u003Cscript setup>\ndefinePageMeta({\n  middleware: ['umbu:auth', 'umbu:two-factor']\n})\n\u003C\u002Fscript>\n",[180,376,377,382,393,401,425,432],{"__ignoreMap":252},[256,378,379],{"class":258,"line":259},[256,380,381],{"class":262},"\u002F\u002F pages\u002Fsensitive-operation.vue\n",[256,383,384,387,390],{"class":258,"line":266},[256,385,386],{"class":277},"\u003C",[256,388,389],{"class":273},"script setup",[256,391,392],{"class":277},">\n",[256,394,395,397,399],{"class":258,"line":281},[256,396,270],{"class":269},[256,398,274],{"class":273},[256,400,278],{"class":277},[256,402,403,405,407,409,411,413,415,417,419,421,423],{"class":258,"line":306},[256,404,285],{"class":284},[256,406,288],{"class":277},[256,408,291],{"class":273},[256,410,294],{"class":277},[256,412,347],{"class":297},[256,414,294],{"class":277},[256,416,352],{"class":277},[256,418,355],{"class":277},[256,420,298],{"class":297},[256,422,294],{"class":277},[256,424,303],{"class":273},[256,426,428,430],{"class":258,"line":427},5,[256,429,309],{"class":277},[256,431,312],{"class":273},[256,433,435,438,441],{"class":258,"line":434},6,[256,436,437],{"class":277},"\u003C\u002F",[256,439,440],{"class":273},"script",[256,442,392],{"class":277},[176,444,445],{},"For conditional 2FA requirements, implement the logic within your page component or create a custom middleware that checks the user's 2FA status before applying protection.",[184,447,449],{"id":448},"how-it-works","How It Works",[192,451,453],{"id":452},"server-side-validation","Server-Side Validation",[176,455,456],{},"On the server, the middleware:",[458,459,460,463,466],"ol",{},[208,461,462],{},"Extracts the 2FA token from cookies",[208,464,465],{},"Validates the 2FA token hasn't expired",[208,467,468],{},"If validation fails: Logs out and redirects to login",[192,470,472],{"id":471},"client-side-validation","Client-Side Validation",[176,474,475],{},"On the client, the middleware:",[458,477,478,481,483,486,489],{},[208,479,480],{},"Extracts the 2FA token from localStorage",[208,482,465],{},[208,484,485],{},"Checks strategy consistency",[208,487,488],{},"Validates user auth state",[208,490,468],{},[184,492,494],{"id":493},"validation-logic","Validation Logic",[192,496,498],{"id":497},"sanctum-validation","Sanctum Validation",[247,500,502],{"className":249,"code":501,"language":251,"meta":252,"style":252},"\u002F\u002F Server-side\nconst token = strategyName\n  ? useCookie\u003Cstring | null>($auth.prefix + `_2fa.` + strategyName).value\n  : null\n\nif (!validateSessionHas2FA(strategyName, token, null, true)) {\n  return await handleLogout(strategyName, redirectPath, 'has2FA')\n}\n\n\u002F\u002F Client-side\nconst token2FA = strategyName\n  ? localStorage.getItem($auth.prefix + `_2fa.` + strategyName)\n  : null\n\nif (!validateSessionHas2FA(strategyName, token2FA, null, false) ||\n    $auth.strategy !== strategyName ||\n    $auth.strategy !== store.value.strategy) {\n  return await handleLogout(strategyName, redirectPath, 'has2FA')\n}\n",[180,503,504,509,524,579,587,593,630,663,669,674,680,692,724,731,736,767,786,812,839],{"__ignoreMap":252},[256,505,506],{"class":258,"line":259},[256,507,508],{"class":262},"\u002F\u002F Server-side\n",[256,510,511,515,518,521],{"class":258,"line":266},[256,512,514],{"class":513},"spNyl","const",[256,516,517],{"class":273}," token ",[256,519,520],{"class":277},"=",[256,522,523],{"class":273}," strategyName\n",[256,525,526,529,532,534,538,541,544,547,550,553,556,559,562,565,568,571,574,576],{"class":258,"line":281},[256,527,528],{"class":277},"  ?",[256,530,531],{"class":269}," useCookie",[256,533,386],{"class":277},[256,535,537],{"class":536},"sBMFI","string",[256,539,540],{"class":277}," |",[256,542,543],{"class":536}," null",[256,545,546],{"class":277},">",[256,548,549],{"class":273},"($auth",[256,551,552],{"class":277},".",[256,554,555],{"class":273},"prefix ",[256,557,558],{"class":277},"+",[256,560,561],{"class":277}," `",[256,563,564],{"class":297},"_2fa.",[256,566,567],{"class":277},"`",[256,569,570],{"class":277}," +",[256,572,573],{"class":273}," strategyName)",[256,575,552],{"class":277},[256,577,578],{"class":273},"value\n",[256,580,581,584],{"class":258,"line":306},[256,582,583],{"class":277},"  :",[256,585,586],{"class":277}," null\n",[256,588,589],{"class":258,"line":427},[256,590,592],{"emptyLinePlaceholder":591},true,"\n",[256,594,595,599,602,605,608,611,613,616,618,621,625,628],{"class":258,"line":434},[256,596,598],{"class":597},"s7zQu","if",[256,600,601],{"class":273}," (",[256,603,604],{"class":277},"!",[256,606,607],{"class":269},"validateSessionHas2FA",[256,609,610],{"class":273},"(strategyName",[256,612,352],{"class":277},[256,614,615],{"class":273}," token",[256,617,352],{"class":277},[256,619,620],{"class":277}," null,",[256,622,624],{"class":623},"sfNiH"," true",[256,626,627],{"class":273},")) ",[256,629,278],{"class":277},[256,631,633,636,639,642,644,647,649,652,654,656,659,661],{"class":258,"line":632},7,[256,634,635],{"class":597},"  return",[256,637,638],{"class":597}," await",[256,640,641],{"class":269}," handleLogout",[256,643,274],{"class":284},[256,645,646],{"class":273},"strategyName",[256,648,352],{"class":277},[256,650,651],{"class":273}," redirectPath",[256,653,352],{"class":277},[256,655,355],{"class":277},[256,657,658],{"class":297},"has2FA",[256,660,294],{"class":277},[256,662,312],{"class":284},[256,664,666],{"class":258,"line":665},8,[256,667,668],{"class":277},"}\n",[256,670,672],{"class":258,"line":671},9,[256,673,592],{"emptyLinePlaceholder":591},[256,675,677],{"class":258,"line":676},10,[256,678,679],{"class":262},"\u002F\u002F Client-side\n",[256,681,683,685,688,690],{"class":258,"line":682},11,[256,684,514],{"class":513},[256,686,687],{"class":273}," token2FA ",[256,689,520],{"class":277},[256,691,523],{"class":273},[256,693,695,697,700,702,705,707,709,711,713,715,717,719,721],{"class":258,"line":694},12,[256,696,528],{"class":277},[256,698,699],{"class":273}," localStorage",[256,701,552],{"class":277},[256,703,704],{"class":269},"getItem",[256,706,549],{"class":273},[256,708,552],{"class":277},[256,710,555],{"class":273},[256,712,558],{"class":277},[256,714,561],{"class":277},[256,716,564],{"class":297},[256,718,567],{"class":277},[256,720,570],{"class":277},[256,722,723],{"class":273}," strategyName)\n",[256,725,727,729],{"class":258,"line":726},13,[256,728,583],{"class":277},[256,730,586],{"class":277},[256,732,734],{"class":258,"line":733},14,[256,735,592],{"emptyLinePlaceholder":591},[256,737,739,741,743,745,747,749,751,754,756,758,761,764],{"class":258,"line":738},15,[256,740,598],{"class":597},[256,742,601],{"class":273},[256,744,604],{"class":277},[256,746,607],{"class":269},[256,748,610],{"class":273},[256,750,352],{"class":277},[256,752,753],{"class":273}," token2FA",[256,755,352],{"class":277},[256,757,620],{"class":277},[256,759,760],{"class":623}," false",[256,762,763],{"class":273},") ",[256,765,766],{"class":277},"||\n",[256,768,770,773,775,778,781,784],{"class":258,"line":769},16,[256,771,772],{"class":273},"    $auth",[256,774,552],{"class":277},[256,776,777],{"class":273},"strategy ",[256,779,780],{"class":277},"!==",[256,782,783],{"class":273}," strategyName ",[256,785,766],{"class":277},[256,787,789,791,793,795,797,800,802,805,807,810],{"class":258,"line":788},17,[256,790,772],{"class":273},[256,792,552],{"class":277},[256,794,777],{"class":273},[256,796,780],{"class":277},[256,798,799],{"class":273}," store",[256,801,552],{"class":277},[256,803,804],{"class":273},"value",[256,806,552],{"class":277},[256,808,809],{"class":273},"strategy) ",[256,811,278],{"class":277},[256,813,815,817,819,821,823,825,827,829,831,833,835,837],{"class":258,"line":814},18,[256,816,635],{"class":597},[256,818,638],{"class":597},[256,820,641],{"class":269},[256,822,274],{"class":284},[256,824,646],{"class":273},[256,826,352],{"class":277},[256,828,651],{"class":273},[256,830,352],{"class":277},[256,832,355],{"class":277},[256,834,658],{"class":297},[256,836,294],{"class":277},[256,838,312],{"class":284},[256,840,842],{"class":258,"line":841},19,[256,843,668],{"class":277},[192,845,847],{"id":846},"passport-validation","Passport Validation",[247,849,851],{"className":249,"code":850,"language":251,"meta":252,"style":252},"\u002F\u002F Server-side\nconst { strategy, token, expires } = extractServerAuthData($auth, '2fa')\n\nif (!validateSession(strategy, token, expires)) {\n  return await handleLogout(strategy, redirectPath, 'has2FA')\n}\n\n\u002F\u002F Client-side\nconst { strategy, token, expires } = extractClientAuthData($auth, '2fa')\n\nif (!validateSession(strategy, token, expires) ||\n    !validateStrategyConsistency($auth, store, strategy)) {\n  return await handleLogout(strategy, redirectPath, 'has2FA')\n}\n",[180,852,853,857,897,901,926,953,957,961,965,1000,1004,1027,1048,1074],{"__ignoreMap":252},[256,854,855],{"class":258,"line":259},[256,856,508],{"class":262},[256,858,859,861,864,867,869,871,873,876,878,881,884,886,888,890,893,895],{"class":258,"line":266},[256,860,514],{"class":513},[256,862,863],{"class":277}," {",[256,865,866],{"class":273}," strategy",[256,868,352],{"class":277},[256,870,615],{"class":273},[256,872,352],{"class":277},[256,874,875],{"class":273}," expires ",[256,877,309],{"class":277},[256,879,880],{"class":277}," =",[256,882,883],{"class":269}," extractServerAuthData",[256,885,549],{"class":273},[256,887,352],{"class":277},[256,889,355],{"class":277},[256,891,892],{"class":297},"2fa",[256,894,294],{"class":277},[256,896,312],{"class":273},[256,898,899],{"class":258,"line":281},[256,900,592],{"emptyLinePlaceholder":591},[256,902,903,905,907,909,912,915,917,919,921,924],{"class":258,"line":306},[256,904,598],{"class":597},[256,906,601],{"class":273},[256,908,604],{"class":277},[256,910,911],{"class":269},"validateSession",[256,913,914],{"class":273},"(strategy",[256,916,352],{"class":277},[256,918,615],{"class":273},[256,920,352],{"class":277},[256,922,923],{"class":273}," expires)) ",[256,925,278],{"class":277},[256,927,928,930,932,934,936,939,941,943,945,947,949,951],{"class":258,"line":427},[256,929,635],{"class":597},[256,931,638],{"class":597},[256,933,641],{"class":269},[256,935,274],{"class":284},[256,937,938],{"class":273},"strategy",[256,940,352],{"class":277},[256,942,651],{"class":273},[256,944,352],{"class":277},[256,946,355],{"class":277},[256,948,658],{"class":297},[256,950,294],{"class":277},[256,952,312],{"class":284},[256,954,955],{"class":258,"line":434},[256,956,668],{"class":277},[256,958,959],{"class":258,"line":632},[256,960,592],{"emptyLinePlaceholder":591},[256,962,963],{"class":258,"line":665},[256,964,679],{"class":262},[256,966,967,969,971,973,975,977,979,981,983,985,988,990,992,994,996,998],{"class":258,"line":671},[256,968,514],{"class":513},[256,970,863],{"class":277},[256,972,866],{"class":273},[256,974,352],{"class":277},[256,976,615],{"class":273},[256,978,352],{"class":277},[256,980,875],{"class":273},[256,982,309],{"class":277},[256,984,880],{"class":277},[256,986,987],{"class":269}," extractClientAuthData",[256,989,549],{"class":273},[256,991,352],{"class":277},[256,993,355],{"class":277},[256,995,892],{"class":297},[256,997,294],{"class":277},[256,999,312],{"class":273},[256,1001,1002],{"class":258,"line":676},[256,1003,592],{"emptyLinePlaceholder":591},[256,1005,1006,1008,1010,1012,1014,1016,1018,1020,1022,1025],{"class":258,"line":682},[256,1007,598],{"class":597},[256,1009,601],{"class":273},[256,1011,604],{"class":277},[256,1013,911],{"class":269},[256,1015,914],{"class":273},[256,1017,352],{"class":277},[256,1019,615],{"class":273},[256,1021,352],{"class":277},[256,1023,1024],{"class":273}," expires) ",[256,1026,766],{"class":277},[256,1028,1029,1032,1035,1037,1039,1041,1043,1046],{"class":258,"line":694},[256,1030,1031],{"class":277},"    !",[256,1033,1034],{"class":269},"validateStrategyConsistency",[256,1036,549],{"class":273},[256,1038,352],{"class":277},[256,1040,799],{"class":273},[256,1042,352],{"class":277},[256,1044,1045],{"class":273}," strategy)) ",[256,1047,278],{"class":277},[256,1049,1050,1052,1054,1056,1058,1060,1062,1064,1066,1068,1070,1072],{"class":258,"line":726},[256,1051,635],{"class":597},[256,1053,638],{"class":597},[256,1055,641],{"class":269},[256,1057,274],{"class":284},[256,1059,938],{"class":273},[256,1061,352],{"class":277},[256,1063,651],{"class":273},[256,1065,352],{"class":277},[256,1067,355],{"class":277},[256,1069,658],{"class":297},[256,1071,294],{"class":277},[256,1073,312],{"class":284},[256,1075,1076],{"class":258,"line":733},[256,1077,668],{"class":277},[184,1079,1081],{"id":1080},"token-storage","Token Storage",[192,1083,1085],{"id":1084},"sanctum-2fa-token-storage","Sanctum 2FA Token Storage",[205,1087,1088,1098],{},[208,1089,1090,1094,1095],{},[1091,1092,1093],"strong",{},"Server",": Stored in a cookie with the pattern ",[180,1096,1097],{},"{prefix}_2fa.{strategy}",[208,1099,1100,1103,1104],{},[1091,1101,1102],{},"Client",": Stored in localStorage with the pattern ",[180,1105,1097],{},[192,1107,1109],{"id":1108},"passport-2fa-token-storage","Passport 2FA Token Storage",[205,1111,1112,1118],{},[208,1113,1114,1094,1116],{},[1091,1115,1093],{},[180,1117,1097],{},[208,1119,1120,1103,1122],{},[1091,1121,1102],{},[180,1123,1097],{},[184,1125,1127],{"id":1126},"redirect-behavior","Redirect Behavior",[176,1129,1130],{},"When 2FA validation fails, the middleware:",[458,1132,1133,1136,1139],{},[208,1134,1135],{},"Logs out the current session",[208,1137,1138],{},"Redirects to the configured login path",[208,1140,1141],{},"The user must complete both login and 2FA verification again",[176,1143,1144],{},"The redirect path is configured in your auth setup:",[247,1146,1148],{"className":249,"code":1147,"language":251,"meta":252,"style":252},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  auth: {\n    redirect: {\n      login: '\u002Flogin',\n      logout: '\u002F',\n      home: '\u002Fdashboard',\n      callback: '\u002Fcallback'\n    }\n  }\n})\n",[180,1149,1150,1155,1170,1180,1189,1206,1222,1238,1253,1258,1263],{"__ignoreMap":252},[256,1151,1152],{"class":258,"line":259},[256,1153,1154],{"class":262},"\u002F\u002F nuxt.config.ts\n",[256,1156,1157,1160,1163,1166,1168],{"class":258,"line":266},[256,1158,1159],{"class":597},"export",[256,1161,1162],{"class":597}," default",[256,1164,1165],{"class":269}," defineNuxtConfig",[256,1167,274],{"class":273},[256,1169,278],{"class":277},[256,1171,1172,1175,1177],{"class":258,"line":281},[256,1173,1174],{"class":284},"  auth",[256,1176,288],{"class":277},[256,1178,1179],{"class":277}," {\n",[256,1181,1182,1185,1187],{"class":258,"line":306},[256,1183,1184],{"class":284},"    redirect",[256,1186,288],{"class":277},[256,1188,1179],{"class":277},[256,1190,1191,1194,1196,1198,1201,1203],{"class":258,"line":427},[256,1192,1193],{"class":284},"      login",[256,1195,288],{"class":277},[256,1197,355],{"class":277},[256,1199,1200],{"class":297},"\u002Flogin",[256,1202,294],{"class":277},[256,1204,1205],{"class":277},",\n",[256,1207,1208,1211,1213,1215,1218,1220],{"class":258,"line":434},[256,1209,1210],{"class":284},"      logout",[256,1212,288],{"class":277},[256,1214,355],{"class":277},[256,1216,1217],{"class":297},"\u002F",[256,1219,294],{"class":277},[256,1221,1205],{"class":277},[256,1223,1224,1227,1229,1231,1234,1236],{"class":258,"line":632},[256,1225,1226],{"class":284},"      home",[256,1228,288],{"class":277},[256,1230,355],{"class":277},[256,1232,1233],{"class":297},"\u002Fdashboard",[256,1235,294],{"class":277},[256,1237,1205],{"class":277},[256,1239,1240,1243,1245,1247,1250],{"class":258,"line":665},[256,1241,1242],{"class":284},"      callback",[256,1244,288],{"class":277},[256,1246,355],{"class":277},[256,1248,1249],{"class":297},"\u002Fcallback",[256,1251,1252],{"class":277},"'\n",[256,1254,1255],{"class":258,"line":671},[256,1256,1257],{"class":277},"    }\n",[256,1259,1260],{"class":258,"line":676},[256,1261,1262],{"class":277},"  }\n",[256,1264,1265,1267],{"class":258,"line":682},[256,1266,309],{"class":277},[256,1268,312],{"class":273},[184,1270,1272],{"id":1271},"examples","Examples",[192,1274,1276],{"id":1275},"protecting-security-settings","Protecting Security Settings",[247,1278,1280],{"className":249,"code":1279,"language":251,"meta":252,"style":252},"\u002F\u002F pages\u002Fsettings\u002Fsecurity.vue\n\u003Cscript setup>\ndefinePageMeta({\n  middleware: ['umbu:auth', 'umbu:two-factor']\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>Security Settings\u003C\u002Fh1>\n    \u003C!-- Protected security settings -->\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[180,1281,1282,1286,1294,1302,1326,1332,1340,1344,1353,1363,1380,1391,1400],{"__ignoreMap":252},[256,1283,1284],{"class":258,"line":259},[256,1285,263],{"class":262},[256,1287,1288,1290,1292],{"class":258,"line":266},[256,1289,386],{"class":277},[256,1291,389],{"class":273},[256,1293,392],{"class":277},[256,1295,1296,1298,1300],{"class":258,"line":281},[256,1297,270],{"class":269},[256,1299,274],{"class":273},[256,1301,278],{"class":277},[256,1303,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324],{"class":258,"line":306},[256,1305,285],{"class":284},[256,1307,288],{"class":277},[256,1309,291],{"class":273},[256,1311,294],{"class":277},[256,1313,347],{"class":297},[256,1315,294],{"class":277},[256,1317,352],{"class":277},[256,1319,355],{"class":277},[256,1321,298],{"class":297},[256,1323,294],{"class":277},[256,1325,303],{"class":273},[256,1327,1328,1330],{"class":258,"line":427},[256,1329,309],{"class":277},[256,1331,312],{"class":273},[256,1333,1334,1336,1338],{"class":258,"line":434},[256,1335,437],{"class":277},[256,1337,440],{"class":273},[256,1339,392],{"class":277},[256,1341,1342],{"class":258,"line":632},[256,1343,592],{"emptyLinePlaceholder":591},[256,1345,1346,1348,1351],{"class":258,"line":665},[256,1347,386],{"class":273},[256,1349,1350],{"class":536},"template",[256,1352,392],{"class":273},[256,1354,1355,1358,1361],{"class":258,"line":671},[256,1356,1357],{"class":273},"  \u003C",[256,1359,1360],{"class":536},"div",[256,1362,392],{"class":273},[256,1364,1365,1368,1371,1374,1376,1378],{"class":258,"line":676},[256,1366,1367],{"class":273},"    \u003C",[256,1369,1370],{"class":536},"h1",[256,1372,1373],{"class":273},">Security Settings",[256,1375,437],{"class":277},[256,1377,1370],{"class":273},[256,1379,392],{"class":277},[256,1381,1382,1385,1388],{"class":258,"line":682},[256,1383,1384],{"class":277},"    \u003C!--",[256,1386,1387],{"class":273}," Protected security settings ",[256,1389,1390],{"class":277},"-->\n",[256,1392,1393,1396,1398],{"class":258,"line":694},[256,1394,1395],{"class":277},"  \u003C\u002F",[256,1397,1360],{"class":273},[256,1399,392],{"class":277},[256,1401,1402,1404,1406],{"class":258,"line":726},[256,1403,437],{"class":277},[256,1405,1350],{"class":273},[256,1407,392],{"class":277},[192,1409,1411],{"id":1410},"protecting-sensitive-operations","Protecting Sensitive Operations",[247,1413,1415],{"className":249,"code":1414,"language":251,"meta":252,"style":252},"\u002F\u002F pages\u002Fpayments\u002Findex.vue\n\u003Cscript setup>\ndefinePageMeta({\n  middleware: ['umbu:auth', 'umbu:two-factor']\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>Payment Methods\u003C\u002Fh1>\n    \u003C!-- Protected payment information -->\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[180,1416,1417,1422,1430,1438,1462,1468,1476,1480,1488,1496,1511,1520,1528],{"__ignoreMap":252},[256,1418,1419],{"class":258,"line":259},[256,1420,1421],{"class":262},"\u002F\u002F pages\u002Fpayments\u002Findex.vue\n",[256,1423,1424,1426,1428],{"class":258,"line":266},[256,1425,386],{"class":277},[256,1427,389],{"class":273},[256,1429,392],{"class":277},[256,1431,1432,1434,1436],{"class":258,"line":281},[256,1433,270],{"class":269},[256,1435,274],{"class":273},[256,1437,278],{"class":277},[256,1439,1440,1442,1444,1446,1448,1450,1452,1454,1456,1458,1460],{"class":258,"line":306},[256,1441,285],{"class":284},[256,1443,288],{"class":277},[256,1445,291],{"class":273},[256,1447,294],{"class":277},[256,1449,347],{"class":297},[256,1451,294],{"class":277},[256,1453,352],{"class":277},[256,1455,355],{"class":277},[256,1457,298],{"class":297},[256,1459,294],{"class":277},[256,1461,303],{"class":273},[256,1463,1464,1466],{"class":258,"line":427},[256,1465,309],{"class":277},[256,1467,312],{"class":273},[256,1469,1470,1472,1474],{"class":258,"line":434},[256,1471,437],{"class":277},[256,1473,440],{"class":273},[256,1475,392],{"class":277},[256,1477,1478],{"class":258,"line":632},[256,1479,592],{"emptyLinePlaceholder":591},[256,1481,1482,1484,1486],{"class":258,"line":665},[256,1483,386],{"class":273},[256,1485,1350],{"class":536},[256,1487,392],{"class":273},[256,1489,1490,1492,1494],{"class":258,"line":671},[256,1491,1357],{"class":273},[256,1493,1360],{"class":536},[256,1495,392],{"class":273},[256,1497,1498,1500,1502,1505,1507,1509],{"class":258,"line":676},[256,1499,1367],{"class":273},[256,1501,1370],{"class":536},[256,1503,1504],{"class":273},">Payment Methods",[256,1506,437],{"class":277},[256,1508,1370],{"class":273},[256,1510,392],{"class":277},[256,1512,1513,1515,1518],{"class":258,"line":682},[256,1514,1384],{"class":277},[256,1516,1517],{"class":273}," Protected payment information ",[256,1519,1390],{"class":277},[256,1521,1522,1524,1526],{"class":258,"line":694},[256,1523,1395],{"class":277},[256,1525,1360],{"class":273},[256,1527,392],{"class":277},[256,1529,1530,1532,1534],{"class":258,"line":726},[256,1531,437],{"class":277},[256,1533,1350],{"class":273},[256,1535,392],{"class":277},[192,1537,1539],{"id":1538},"conditional-2fa-based-on-user","Conditional 2FA Based on User",[247,1541,1543],{"className":249,"code":1542,"language":251,"meta":252,"style":252},"\u002F\u002F pages\u002Fadmin\u002Fusers.vue\n\u003Cscript setup>\ndefinePageMeta({\n  middleware: ['umbu:auth', 'umbu:two-factor']\n})\n\u003C\u002Fscript>\n",[180,1544,1545,1550,1558,1566,1590,1596],{"__ignoreMap":252},[256,1546,1547],{"class":258,"line":259},[256,1548,1549],{"class":262},"\u002F\u002F pages\u002Fadmin\u002Fusers.vue\n",[256,1551,1552,1554,1556],{"class":258,"line":266},[256,1553,386],{"class":277},[256,1555,389],{"class":273},[256,1557,392],{"class":277},[256,1559,1560,1562,1564],{"class":258,"line":281},[256,1561,270],{"class":269},[256,1563,274],{"class":273},[256,1565,278],{"class":277},[256,1567,1568,1570,1572,1574,1576,1578,1580,1582,1584,1586,1588],{"class":258,"line":306},[256,1569,285],{"class":284},[256,1571,288],{"class":277},[256,1573,291],{"class":273},[256,1575,294],{"class":277},[256,1577,347],{"class":297},[256,1579,294],{"class":277},[256,1581,352],{"class":277},[256,1583,355],{"class":277},[256,1585,298],{"class":297},[256,1587,294],{"class":277},[256,1589,303],{"class":273},[256,1591,1592,1594],{"class":258,"line":427},[256,1593,309],{"class":277},[256,1595,312],{"class":273},[256,1597,1598,1600,1602],{"class":258,"line":434},[256,1599,437],{"class":277},[256,1601,440],{"class":273},[256,1603,392],{"class":277},[176,1605,1606],{},"For user-specific 2FA requirements, implement the logic within your page component or create a custom middleware that checks the user's 2FA status before applying protection.",[184,1608,1610],{"id":1609},"error-handling","Error Handling",[176,1612,1613],{},"The middleware automatically handles 2FA authentication errors:",[205,1615,1616,1622,1627,1632],{},[208,1617,1618,1621],{},[1091,1619,1620],{},"Missing 2FA token",": Logs out and redirects",[208,1623,1624,1621],{},[1091,1625,1626],{},"Expired 2FA token",[208,1628,1629,1621],{},[1091,1630,1631],{},"Invalid 2FA token",[208,1633,1634,1621],{},[1091,1635,1636],{},"Strategy mismatch",[184,1638,1640],{"id":1639},"best-practices","Best Practices",[192,1642,1644],{"id":1643},"when-to-use-two-factor-middleware","When to Use Two-Factor Middleware",[176,1646,1647],{},"Use the two-factor middleware for:",[205,1649,1650,1653,1656,1659,1662],{},[208,1651,1652],{},"Security settings pages",[208,1654,1655],{},"Payment information pages",[208,1657,1658],{},"Administrative panels",[208,1660,1661],{},"Sensitive operations (password changes, email changes)",[208,1663,1664],{},"API endpoints that handle sensitive data",[192,1666,1668],{"id":1667},"combining-with-auth-middleware","Combining with Auth Middleware",[176,1670,1671],{},"Always combine with the auth middleware:",[247,1673,1675],{"className":249,"code":1674,"language":251,"meta":252,"style":252},"\u002F\u002F Good\ndefinePageMeta({\n  middleware: ['umbu:auth', 'umbu:two-factor']\n})\n\n\u002F\u002F Not recommended - 2FA alone doesn't validate basic auth\ndefinePageMeta({\n  middleware: ['umbu:two-factor']\n})\n",[180,1676,1677,1682,1690,1714,1720,1724,1729,1737,1753],{"__ignoreMap":252},[256,1678,1679],{"class":258,"line":259},[256,1680,1681],{"class":262},"\u002F\u002F Good\n",[256,1683,1684,1686,1688],{"class":258,"line":266},[256,1685,270],{"class":269},[256,1687,274],{"class":273},[256,1689,278],{"class":277},[256,1691,1692,1694,1696,1698,1700,1702,1704,1706,1708,1710,1712],{"class":258,"line":281},[256,1693,285],{"class":284},[256,1695,288],{"class":277},[256,1697,291],{"class":273},[256,1699,294],{"class":277},[256,1701,347],{"class":297},[256,1703,294],{"class":277},[256,1705,352],{"class":277},[256,1707,355],{"class":277},[256,1709,298],{"class":297},[256,1711,294],{"class":277},[256,1713,303],{"class":273},[256,1715,1716,1718],{"class":258,"line":306},[256,1717,309],{"class":277},[256,1719,312],{"class":273},[256,1721,1722],{"class":258,"line":427},[256,1723,592],{"emptyLinePlaceholder":591},[256,1725,1726],{"class":258,"line":434},[256,1727,1728],{"class":262},"\u002F\u002F Not recommended - 2FA alone doesn't validate basic auth\n",[256,1730,1731,1733,1735],{"class":258,"line":632},[256,1732,270],{"class":269},[256,1734,274],{"class":273},[256,1736,278],{"class":277},[256,1738,1739,1741,1743,1745,1747,1749,1751],{"class":258,"line":665},[256,1740,285],{"class":284},[256,1742,288],{"class":277},[256,1744,291],{"class":273},[256,1746,294],{"class":277},[256,1748,298],{"class":297},[256,1750,294],{"class":277},[256,1752,303],{"class":273},[256,1754,1755,1757],{"class":258,"line":671},[256,1756,309],{"class":277},[256,1758,312],{"class":273},[192,1760,1762],{"id":1761},"user-experience-considerations","User Experience Considerations",[205,1764,1765,1768,1771,1774],{},[208,1766,1767],{},"Inform users when 2FA is required",[208,1769,1770],{},"Provide clear messaging about 2FA requirements",[208,1772,1773],{},"Allow users to enable\u002Fdisable 2FA in their settings",[208,1775,1776],{},"Consider implementing \"remember this device\" for better UX",[184,1778,1780],{"id":1779},"notes","Notes",[205,1782,1783,1788,1791,1794,1797,1800],{},[208,1784,178,1785,1787],{},[180,1786,298],{}," middleware is automatically registered by the module",[208,1789,1790],{},"No manual import required",[208,1792,1793],{},"Works with both Sanctum and Passport providers",[208,1795,1796],{},"Validation logic differs between providers",[208,1798,1799],{},"Automatic logout on validation failure",[208,1801,1802,1803,1805],{},"Should always be combined with the ",[180,1804,347],{}," middleware",[1807,1808,1809],"style",{},"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 .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 .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 .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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":252,"searchDepth":259,"depth":266,"links":1811},[1812,1815,1820,1824,1828,1832,1833,1838,1839,1844],{"id":186,"depth":266,"text":187,"children":1813},[1814],{"id":194,"depth":281,"text":195},{"id":240,"depth":266,"text":241,"children":1816},[1817,1818,1819],{"id":244,"depth":281,"text":245},{"id":315,"depth":281,"text":316},{"id":370,"depth":281,"text":371},{"id":448,"depth":266,"text":449,"children":1821},[1822,1823],{"id":452,"depth":281,"text":453},{"id":471,"depth":281,"text":472},{"id":493,"depth":266,"text":494,"children":1825},[1826,1827],{"id":497,"depth":281,"text":498},{"id":846,"depth":281,"text":847},{"id":1080,"depth":266,"text":1081,"children":1829},[1830,1831],{"id":1084,"depth":281,"text":1085},{"id":1108,"depth":281,"text":1109},{"id":1126,"depth":266,"text":1127},{"id":1271,"depth":266,"text":1272,"children":1834},[1835,1836,1837],{"id":1275,"depth":281,"text":1276},{"id":1410,"depth":281,"text":1411},{"id":1538,"depth":281,"text":1539},{"id":1609,"depth":266,"text":1610},{"id":1639,"depth":266,"text":1640,"children":1840},[1841,1842,1843],{"id":1643,"depth":281,"text":1644},{"id":1667,"depth":281,"text":1668},{"id":1761,"depth":281,"text":1762},{"id":1779,"depth":266,"text":1780},"Route middleware to protect 2FA-enabled routes","md",null,{},{"icon":65},{"title":117,"description":1845},"3s3eUzuuiza_bVx15L6kaj4gHorj6ZDPYVHbCF-jowU",[1853,1855],{"title":112,"path":113,"stem":114,"description":1854,"icon":115,"children":-1},"Route middleware to protect authenticated routes",{"title":121,"path":126,"stem":127,"description":1856,"icon":128,"children":-1},"Nuxt hooks used by Nuxt Umbu for module integration",1785126614915]