[{"data":1,"prerenderedAt":3297},["ShallowReactive",2],{"navigation":3,"\u002Fadvanced\u002Fsecurity-features":170,"\u002Fadvanced\u002Fsecurity-features-surround":3292},[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":162,"body":172,"description":3285,"extension":3286,"links":3287,"meta":3288,"navigation":3289,"path":163,"seo":3290,"stem":164,"__hash__":3291},"docs\u002F7.advanced\u002F6.security-features.md",{"type":173,"value":174,"toc":3243},"minimark",[175,179,184,187,209,212,217,220,224,227,335,339,366,370,375,378,519,523,526,647,651,655,706,710,713,781,785,788,835,839,843,846,850,853,1129,1133,1137,1219,1223,1321,1325,1329,1332,1463,1467,1610,1614,1959,1963,1966,2045,2049,2052,2130,2134,2196,2200,2203,2296,2300,2357,2361,2518,2522,2526,2532,2537,2577,2581,2586,2590,2604,2608,2613,2617,2692,2696,2700,2832,2836,3011,3015,3019,3073,3077,3116,3120,3124,3129,3143,3148,3162,3166,3171,3185,3190,3203,3207,3239],[176,177,178],"p",{},"Learn about security features in Nuxt Umbu, including CSRF protection and two-factor authentication (2FA) implementation.",[180,181,183],"h2",{"id":182},"overview","Overview",[176,185,186],{},"Nuxt Umbu provides built-in security features to protect your authentication system:",[188,189,190,198,203],"ul",{},[191,192,193,197],"li",{},[194,195,196],"strong",{},"CSRF Protection",": Cross-Site Request Forgery protection for Sanctum",[191,199,200,202],{},[194,201,62],{},": Optional 2FA support for enhanced security",[191,204,205,208],{},[194,206,207],{},"Secure Cookie Configuration",": Production-ready cookie security settings",[180,210,196],{"id":211},"csrf-protection",[213,214,216],"h3",{"id":215},"what-is-csrf","What is CSRF?",[176,218,219],{},"Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated.",[213,221,223],{"id":222},"sanctum-csrf","Sanctum CSRF",[176,225,226],{},"Nuxt Umbu integrates with Laravel Sanctum's CSRF protection:",[228,229,234],"pre",{"className":230,"code":231,"language":232,"meta":233,"style":233},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  auth: {\n    provider: 'sanctum',\n    csrf: '\u002Fsanctum\u002Fcsrf-cookie'  \u002F\u002F CSRF cookie endpoint\n  }\n})\n","typescript","",[235,236,237,246,268,281,302,320,326],"code",{"__ignoreMap":233},[238,239,242],"span",{"class":240,"line":241},"line",1,[238,243,245],{"class":244},"sHwdD","\u002F\u002F nuxt.config.ts\n",[238,247,249,253,256,260,264],{"class":240,"line":248},2,[238,250,252],{"class":251},"s7zQu","export",[238,254,255],{"class":251}," default",[238,257,259],{"class":258},"s2Zo4"," defineNuxtConfig",[238,261,263],{"class":262},"sTEyZ","(",[238,265,267],{"class":266},"sMK4o","{\n",[238,269,271,275,278],{"class":240,"line":270},3,[238,272,274],{"class":273},"swJcz","  auth",[238,276,277],{"class":266},":",[238,279,280],{"class":266}," {\n",[238,282,284,287,289,292,296,299],{"class":240,"line":283},4,[238,285,286],{"class":273},"    provider",[238,288,277],{"class":266},[238,290,291],{"class":266}," '",[238,293,295],{"class":294},"sfazB","sanctum",[238,297,298],{"class":266},"'",[238,300,301],{"class":266},",\n",[238,303,305,308,310,312,315,317],{"class":240,"line":304},5,[238,306,307],{"class":273},"    csrf",[238,309,277],{"class":266},[238,311,291],{"class":266},[238,313,314],{"class":294},"\u002Fsanctum\u002Fcsrf-cookie",[238,316,298],{"class":266},[238,318,319],{"class":244},"  \u002F\u002F CSRF cookie endpoint\n",[238,321,323],{"class":240,"line":322},6,[238,324,325],{"class":266},"  }\n",[238,327,329,332],{"class":240,"line":328},7,[238,330,331],{"class":266},"}",[238,333,334],{"class":262},")\n",[213,336,338],{"id":337},"how-csrf-works","How CSRF Works",[340,341,342,348,354,360],"ol",{},[191,343,344,347],{},[194,345,346],{},"Initial Request",": Client requests CSRF cookie",[191,349,350,353],{},[194,351,352],{},"Cookie Set",": Server sets CSRF cookie",[191,355,356,359],{},[194,357,358],{},"Subsequent Requests",": Client includes CSRF token in headers",[191,361,362,365],{},[194,363,364],{},"Validation",": Server validates token before processing",[213,367,369],{"id":368},"using-csrf-protection","Using CSRF Protection",[371,372,374],"h4",{"id":373},"automatic-csrf-handling","Automatic CSRF Handling",[176,376,377],{},"Nuxt Umbu automatically handles CSRF for Sanctum:",[228,379,381],{"className":230,"code":380,"language":232,"meta":233,"style":233},"import { ensureCsrf } from '#auth-utils'\n\n\u002F\u002F Ensure CSRF token is present before authenticated requests\nawait ensureCsrf()\n\n\u002F\u002F Now make authenticated requests\nconst response = await $fetch('\u002Fapi\u002Fprotected', {\n  method: 'POST',\n  body: { data: 'value' }\n})\n",[235,382,383,408,414,419,429,433,438,470,487,512],{"__ignoreMap":233},[238,384,385,388,391,394,397,400,402,405],{"class":240,"line":241},[238,386,387],{"class":251},"import",[238,389,390],{"class":266}," {",[238,392,393],{"class":262}," ensureCsrf",[238,395,396],{"class":266}," }",[238,398,399],{"class":251}," from",[238,401,291],{"class":266},[238,403,404],{"class":294},"#auth-utils",[238,406,407],{"class":266},"'\n",[238,409,410],{"class":240,"line":248},[238,411,413],{"emptyLinePlaceholder":412},true,"\n",[238,415,416],{"class":240,"line":270},[238,417,418],{"class":244},"\u002F\u002F Ensure CSRF token is present before authenticated requests\n",[238,420,421,424,426],{"class":240,"line":283},[238,422,423],{"class":251},"await",[238,425,393],{"class":258},[238,427,428],{"class":262},"()\n",[238,430,431],{"class":240,"line":304},[238,432,413],{"emptyLinePlaceholder":412},[238,434,435],{"class":240,"line":322},[238,436,437],{"class":244},"\u002F\u002F Now make authenticated requests\n",[238,439,440,444,447,450,453,456,458,460,463,465,468],{"class":240,"line":328},[238,441,443],{"class":442},"spNyl","const",[238,445,446],{"class":262}," response ",[238,448,449],{"class":266},"=",[238,451,452],{"class":251}," await",[238,454,455],{"class":258}," $fetch",[238,457,263],{"class":262},[238,459,298],{"class":266},[238,461,462],{"class":294},"\u002Fapi\u002Fprotected",[238,464,298],{"class":266},[238,466,467],{"class":266},",",[238,469,280],{"class":266},[238,471,473,476,478,480,483,485],{"class":240,"line":472},8,[238,474,475],{"class":273},"  method",[238,477,277],{"class":266},[238,479,291],{"class":266},[238,481,482],{"class":294},"POST",[238,484,298],{"class":266},[238,486,301],{"class":266},[238,488,490,493,495,497,500,502,504,507,509],{"class":240,"line":489},9,[238,491,492],{"class":273},"  body",[238,494,277],{"class":266},[238,496,390],{"class":266},[238,498,499],{"class":273}," data",[238,501,277],{"class":266},[238,503,291],{"class":266},[238,505,506],{"class":294},"value",[238,508,298],{"class":266},[238,510,511],{"class":266}," }\n",[238,513,515,517],{"class":240,"line":514},10,[238,516,331],{"class":266},[238,518,334],{"class":262},[371,520,522],{"id":521},"manual-csrf-token","Manual CSRF Token",[176,524,525],{},"If you need the CSRF token manually:",[228,527,529],{"className":230,"code":528,"language":232,"meta":233,"style":233},"import { useAuthStore } from '#auth-utils'\n\nconst authStore = useAuthStore()\nconst csrfToken = authStore.csrfToken\n\n\u002F\u002F Use in custom requests\nawait $fetch('\u002Fapi\u002Fprotected', {\n  headers: {\n    'X-XSRF-TOKEN': csrfToken\n  }\n})\n",[235,530,531,550,554,567,585,589,594,612,621,636,640],{"__ignoreMap":233},[238,532,533,535,537,540,542,544,546,548],{"class":240,"line":241},[238,534,387],{"class":251},[238,536,390],{"class":266},[238,538,539],{"class":262}," useAuthStore",[238,541,396],{"class":266},[238,543,399],{"class":251},[238,545,291],{"class":266},[238,547,404],{"class":294},[238,549,407],{"class":266},[238,551,552],{"class":240,"line":248},[238,553,413],{"emptyLinePlaceholder":412},[238,555,556,558,561,563,565],{"class":240,"line":270},[238,557,443],{"class":442},[238,559,560],{"class":262}," authStore ",[238,562,449],{"class":266},[238,564,539],{"class":258},[238,566,428],{"class":262},[238,568,569,571,574,576,579,582],{"class":240,"line":283},[238,570,443],{"class":442},[238,572,573],{"class":262}," csrfToken ",[238,575,449],{"class":266},[238,577,578],{"class":262}," authStore",[238,580,581],{"class":266},".",[238,583,584],{"class":262},"csrfToken\n",[238,586,587],{"class":240,"line":304},[238,588,413],{"emptyLinePlaceholder":412},[238,590,591],{"class":240,"line":322},[238,592,593],{"class":244},"\u002F\u002F Use in custom requests\n",[238,595,596,598,600,602,604,606,608,610],{"class":240,"line":328},[238,597,423],{"class":251},[238,599,455],{"class":258},[238,601,263],{"class":262},[238,603,298],{"class":266},[238,605,462],{"class":294},[238,607,298],{"class":266},[238,609,467],{"class":266},[238,611,280],{"class":266},[238,613,614,617,619],{"class":240,"line":472},[238,615,616],{"class":273},"  headers",[238,618,277],{"class":266},[238,620,280],{"class":266},[238,622,623,626,629,631,633],{"class":240,"line":489},[238,624,625],{"class":266},"    '",[238,627,628],{"class":273},"X-XSRF-TOKEN",[238,630,298],{"class":266},[238,632,277],{"class":266},[238,634,635],{"class":262}," csrfToken\n",[238,637,638],{"class":240,"line":514},[238,639,325],{"class":266},[238,641,643,645],{"class":240,"line":642},11,[238,644,331],{"class":266},[238,646,334],{"class":262},[213,648,650],{"id":649},"csrf-configuration","CSRF Configuration",[371,652,654],{"id":653},"custom-csrf-endpoint","Custom CSRF Endpoint",[228,656,658],{"className":230,"code":657,"language":232,"meta":233,"style":233},"auth: {\n  provider: 'sanctum',\n  csrf: '\u002Fapi\u002Fcsrf-token'  \u002F\u002F Custom endpoint\n}\n",[235,659,660,669,684,701],{"__ignoreMap":233},[238,661,662,665,667],{"class":240,"line":241},[238,663,112],{"class":664},"sBMFI",[238,666,277],{"class":266},[238,668,280],{"class":266},[238,670,671,674,676,678,680,682],{"class":240,"line":248},[238,672,673],{"class":664},"  provider",[238,675,277],{"class":266},[238,677,291],{"class":266},[238,679,295],{"class":294},[238,681,298],{"class":266},[238,683,301],{"class":266},[238,685,686,689,691,693,696,698],{"class":240,"line":270},[238,687,688],{"class":664},"  csrf",[238,690,277],{"class":266},[238,692,291],{"class":266},[238,694,695],{"class":294},"\u002Fapi\u002Fcsrf-token",[238,697,298],{"class":266},[238,699,700],{"class":244},"  \u002F\u002F Custom endpoint\n",[238,702,703],{"class":240,"line":283},[238,704,705],{"class":266},"}\n",[371,707,709],{"id":708},"csrf-in-development","CSRF in Development",[176,711,712],{},"CSRF is automatically handled in development with relaxed security:",[228,714,716],{"className":230,"code":715,"language":232,"meta":233,"style":233},"if (isDev) {\n  options.cookie.prefix = 'auth.'\n  options.cookie.options.secure = false\n}\n",[235,717,718,728,753,777],{"__ignoreMap":233},[238,719,720,723,726],{"class":240,"line":241},[238,721,722],{"class":251},"if",[238,724,725],{"class":262}," (isDev) ",[238,727,267],{"class":266},[238,729,730,733,735,738,740,743,746,748,751],{"class":240,"line":248},[238,731,732],{"class":262},"  options",[238,734,581],{"class":266},[238,736,737],{"class":262},"cookie",[238,739,581],{"class":266},[238,741,742],{"class":262},"prefix",[238,744,745],{"class":266}," =",[238,747,291],{"class":266},[238,749,750],{"class":294},"auth.",[238,752,407],{"class":266},[238,754,755,757,759,761,763,766,768,771,773],{"class":240,"line":270},[238,756,732],{"class":262},[238,758,581],{"class":266},[238,760,737],{"class":262},[238,762,581],{"class":266},[238,764,765],{"class":262},"options",[238,767,581],{"class":266},[238,769,770],{"class":262},"secure",[238,772,745],{"class":266},[238,774,776],{"class":775},"sfNiH"," false\n",[238,778,779],{"class":240,"line":283},[238,780,705],{"class":266},[213,782,784],{"id":783},"passport-csrf-optional","Passport CSRF (Optional)",[176,786,787],{},"Passport provider can optionally use CSRF:",[228,789,791],{"className":230,"code":790,"language":232,"meta":233,"style":233},"auth: {\n  provider: 'passport',\n  csrf: '\u002Fapi\u002Fcsrf-token'  \u002F\u002F Optional CSRF endpoint\n}\n",[235,792,793,801,816,831],{"__ignoreMap":233},[238,794,795,797,799],{"class":240,"line":241},[238,796,112],{"class":664},[238,798,277],{"class":266},[238,800,280],{"class":266},[238,802,803,805,807,809,812,814],{"class":240,"line":248},[238,804,673],{"class":664},[238,806,277],{"class":266},[238,808,291],{"class":266},[238,810,811],{"class":294},"passport",[238,813,298],{"class":266},[238,815,301],{"class":266},[238,817,818,820,822,824,826,828],{"class":240,"line":270},[238,819,688],{"class":664},[238,821,277],{"class":266},[238,823,291],{"class":266},[238,825,695],{"class":294},[238,827,298],{"class":266},[238,829,830],{"class":244},"  \u002F\u002F Optional CSRF endpoint\n",[238,832,833],{"class":240,"line":283},[238,834,705],{"class":266},[180,836,838],{"id":837},"two-factor-authentication-2fa","Two-Factor Authentication (2FA)",[213,840,842],{"id":841},"what-is-2fa","What is 2FA?",[176,844,845],{},"Two-Factor Authentication adds an extra layer of security by requiring a second form of verification in addition to your password.",[213,847,849],{"id":848},"enabling-2fa","Enabling 2FA",[176,851,852],{},"2FA is automatically enabled when you configure a twoFactor endpoint:",[228,854,856],{"className":230,"code":855,"language":232,"meta":233,"style":233},"strategies: {\n  password: {\n    endpoints: {\n      login: { url: '\u002Foauth\u002Ftoken', method: 'post' },\n      user: { url: '\u002Fapi\u002Fuser', method: 'get' },\n      twoFactor: {\n        url: '\u002Fapi\u002F2fa\u002Fverify',\n        method: 'post',\n        property: 'access_token',\n        expires: 'expires_in',\n        headerName: 'X-2FA-Token'\n      }\n    },\n    redirect: {\n      login: '\u002Flogin',\n      logout: '\u002F',\n      twoFactor: '\u002F2fa'\n    }\n  }\n}\n",[235,857,858,867,876,885,923,958,967,983,998,1014,1030,1044,1050,1056,1066,1082,1099,1113,1119,1124],{"__ignoreMap":233},[238,859,860,863,865],{"class":240,"line":241},[238,861,862],{"class":664},"strategies",[238,864,277],{"class":266},[238,866,280],{"class":266},[238,868,869,872,874],{"class":240,"line":248},[238,870,871],{"class":664},"  password",[238,873,277],{"class":266},[238,875,280],{"class":266},[238,877,878,881,883],{"class":240,"line":270},[238,879,880],{"class":664},"    endpoints",[238,882,277],{"class":266},[238,884,280],{"class":266},[238,886,887,890,892,894,897,899,901,904,906,908,911,913,915,918,920],{"class":240,"line":283},[238,888,889],{"class":664},"      login",[238,891,277],{"class":266},[238,893,390],{"class":266},[238,895,896],{"class":664}," url",[238,898,277],{"class":266},[238,900,291],{"class":266},[238,902,903],{"class":294},"\u002Foauth\u002Ftoken",[238,905,298],{"class":266},[238,907,467],{"class":266},[238,909,910],{"class":664}," method",[238,912,277],{"class":266},[238,914,291],{"class":266},[238,916,917],{"class":294},"post",[238,919,298],{"class":266},[238,921,922],{"class":266}," },\n",[238,924,925,928,930,932,934,936,938,941,943,945,947,949,951,954,956],{"class":240,"line":304},[238,926,927],{"class":664},"      user",[238,929,277],{"class":266},[238,931,390],{"class":266},[238,933,896],{"class":664},[238,935,277],{"class":266},[238,937,291],{"class":266},[238,939,940],{"class":294},"\u002Fapi\u002Fuser",[238,942,298],{"class":266},[238,944,467],{"class":266},[238,946,910],{"class":664},[238,948,277],{"class":266},[238,950,291],{"class":266},[238,952,953],{"class":294},"get",[238,955,298],{"class":266},[238,957,922],{"class":266},[238,959,960,963,965],{"class":240,"line":322},[238,961,962],{"class":664},"      twoFactor",[238,964,277],{"class":266},[238,966,280],{"class":266},[238,968,969,972,974,976,979,981],{"class":240,"line":328},[238,970,971],{"class":664},"        url",[238,973,277],{"class":266},[238,975,291],{"class":266},[238,977,978],{"class":294},"\u002Fapi\u002F2fa\u002Fverify",[238,980,298],{"class":266},[238,982,301],{"class":266},[238,984,985,988,990,992,994,996],{"class":240,"line":472},[238,986,987],{"class":664},"        method",[238,989,277],{"class":266},[238,991,291],{"class":266},[238,993,917],{"class":294},[238,995,298],{"class":266},[238,997,301],{"class":266},[238,999,1000,1003,1005,1007,1010,1012],{"class":240,"line":489},[238,1001,1002],{"class":664},"        property",[238,1004,277],{"class":266},[238,1006,291],{"class":266},[238,1008,1009],{"class":294},"access_token",[238,1011,298],{"class":266},[238,1013,301],{"class":266},[238,1015,1016,1019,1021,1023,1026,1028],{"class":240,"line":514},[238,1017,1018],{"class":664},"        expires",[238,1020,277],{"class":266},[238,1022,291],{"class":266},[238,1024,1025],{"class":294},"expires_in",[238,1027,298],{"class":266},[238,1029,301],{"class":266},[238,1031,1032,1035,1037,1039,1042],{"class":240,"line":642},[238,1033,1034],{"class":664},"        headerName",[238,1036,277],{"class":266},[238,1038,291],{"class":266},[238,1040,1041],{"class":294},"X-2FA-Token",[238,1043,407],{"class":266},[238,1045,1047],{"class":240,"line":1046},12,[238,1048,1049],{"class":266},"      }\n",[238,1051,1053],{"class":240,"line":1052},13,[238,1054,1055],{"class":266},"    },\n",[238,1057,1059,1062,1064],{"class":240,"line":1058},14,[238,1060,1061],{"class":664},"    redirect",[238,1063,277],{"class":266},[238,1065,280],{"class":266},[238,1067,1069,1071,1073,1075,1078,1080],{"class":240,"line":1068},15,[238,1070,889],{"class":664},[238,1072,277],{"class":266},[238,1074,291],{"class":266},[238,1076,1077],{"class":294},"\u002Flogin",[238,1079,298],{"class":266},[238,1081,301],{"class":266},[238,1083,1085,1088,1090,1092,1095,1097],{"class":240,"line":1084},16,[238,1086,1087],{"class":664},"      logout",[238,1089,277],{"class":266},[238,1091,291],{"class":266},[238,1093,1094],{"class":294},"\u002F",[238,1096,298],{"class":266},[238,1098,301],{"class":266},[238,1100,1102,1104,1106,1108,1111],{"class":240,"line":1101},17,[238,1103,962],{"class":664},[238,1105,277],{"class":266},[238,1107,291],{"class":266},[238,1109,1110],{"class":294},"\u002F2fa",[238,1112,407],{"class":266},[238,1114,1116],{"class":240,"line":1115},18,[238,1117,1118],{"class":266},"    }\n",[238,1120,1122],{"class":240,"line":1121},19,[238,1123,325],{"class":266},[238,1125,1127],{"class":240,"line":1126},20,[238,1128,705],{"class":266},[213,1130,1132],{"id":1131},"_2fa-configuration-options","2FA Configuration Options",[371,1134,1136],{"id":1135},"twofactorfetchoption","TwoFactorFetchOption",[228,1138,1140],{"className":230,"code":1139,"language":232,"meta":233,"style":233},"type TwoFactorFetchOption = {\n  url: string              \u002F\u002F 2FA verification endpoint\n  method: string           \u002F\u002F HTTP method\n  property?: string       \u002F\u002F Where token comes from (default: access_token)\n  expires?: string        \u002F\u002F Where expiration comes from (default: expires_in)\n  headerName?: string     \u002F\u002F Header name for token (default: '2fa')\n}\n",[235,1141,1142,1154,1167,1178,1191,1203,1215],{"__ignoreMap":233},[238,1143,1144,1147,1150,1152],{"class":240,"line":241},[238,1145,1146],{"class":442},"type",[238,1148,1149],{"class":664}," TwoFactorFetchOption",[238,1151,745],{"class":266},[238,1153,280],{"class":266},[238,1155,1156,1159,1161,1164],{"class":240,"line":248},[238,1157,1158],{"class":273},"  url",[238,1160,277],{"class":266},[238,1162,1163],{"class":664}," string",[238,1165,1166],{"class":244},"              \u002F\u002F 2FA verification endpoint\n",[238,1168,1169,1171,1173,1175],{"class":240,"line":270},[238,1170,475],{"class":273},[238,1172,277],{"class":266},[238,1174,1163],{"class":664},[238,1176,1177],{"class":244},"           \u002F\u002F HTTP method\n",[238,1179,1180,1183,1186,1188],{"class":240,"line":283},[238,1181,1182],{"class":273},"  property",[238,1184,1185],{"class":266},"?:",[238,1187,1163],{"class":664},[238,1189,1190],{"class":244},"       \u002F\u002F Where token comes from (default: access_token)\n",[238,1192,1193,1196,1198,1200],{"class":240,"line":304},[238,1194,1195],{"class":273},"  expires",[238,1197,1185],{"class":266},[238,1199,1163],{"class":664},[238,1201,1202],{"class":244},"        \u002F\u002F Where expiration comes from (default: expires_in)\n",[238,1204,1205,1208,1210,1212],{"class":240,"line":322},[238,1206,1207],{"class":273},"  headerName",[238,1209,1185],{"class":266},[238,1211,1163],{"class":664},[238,1213,1214],{"class":244},"     \u002F\u002F Header name for token (default: '2fa')\n",[238,1216,1217],{"class":240,"line":328},[238,1218,705],{"class":266},[371,1220,1222],{"id":1221},"configuration-example","Configuration Example",[228,1224,1226],{"className":230,"code":1225,"language":232,"meta":233,"style":233},"twoFactor: {\n  url: '\u002Fapi\u002F2fa\u002Fverify',\n  method: 'post',\n  property: 'token',           \u002F\u002F Response property containing token\n  expires: 'expires',          \u002F\u002F Response property containing expiration\n  headerName: 'Authorization' \u002F\u002F Custom header name\n}\n",[235,1227,1228,1237,1251,1265,1283,1301,1317],{"__ignoreMap":233},[238,1229,1230,1233,1235],{"class":240,"line":241},[238,1231,1232],{"class":664},"twoFactor",[238,1234,277],{"class":266},[238,1236,280],{"class":266},[238,1238,1239,1241,1243,1245,1247,1249],{"class":240,"line":248},[238,1240,1158],{"class":664},[238,1242,277],{"class":266},[238,1244,291],{"class":266},[238,1246,978],{"class":294},[238,1248,298],{"class":266},[238,1250,301],{"class":266},[238,1252,1253,1255,1257,1259,1261,1263],{"class":240,"line":270},[238,1254,475],{"class":664},[238,1256,277],{"class":266},[238,1258,291],{"class":266},[238,1260,917],{"class":294},[238,1262,298],{"class":266},[238,1264,301],{"class":266},[238,1266,1267,1269,1271,1273,1276,1278,1280],{"class":240,"line":283},[238,1268,1182],{"class":664},[238,1270,277],{"class":266},[238,1272,291],{"class":266},[238,1274,1275],{"class":294},"token",[238,1277,298],{"class":266},[238,1279,467],{"class":266},[238,1281,1282],{"class":244},"           \u002F\u002F Response property containing token\n",[238,1284,1285,1287,1289,1291,1294,1296,1298],{"class":240,"line":304},[238,1286,1195],{"class":664},[238,1288,277],{"class":266},[238,1290,291],{"class":266},[238,1292,1293],{"class":294},"expires",[238,1295,298],{"class":266},[238,1297,467],{"class":266},[238,1299,1300],{"class":244},"          \u002F\u002F Response property containing expiration\n",[238,1302,1303,1305,1307,1309,1312,1314],{"class":240,"line":322},[238,1304,1207],{"class":664},[238,1306,277],{"class":266},[238,1308,291],{"class":266},[238,1310,1311],{"class":294},"Authorization",[238,1313,298],{"class":266},[238,1315,1316],{"class":244}," \u002F\u002F Custom header name\n",[238,1318,1319],{"class":240,"line":328},[238,1320,705],{"class":266},[213,1322,1324],{"id":1323},"using-2fa","Using 2FA",[371,1326,1328],{"id":1327},"middleware-protection","Middleware Protection",[176,1330,1331],{},"When 2FA is enabled, the middleware automatically protects routes:",[228,1333,1335],{"className":230,"code":1334,"language":232,"meta":233,"style":233},"\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  auth: {\n    \u002F\u002F 2FA endpoint configured\n    strategies: {\n      password: {\n        endpoints: {\n          twoFactor: { url: '\u002Fapi\u002F2fa\u002Fverify', method: 'post' }\n        }\n      }\n    }\n  }\n})\n\n\u002F\u002F Middleware is automatically registered\n\u002F\u002F Routes with twoFactor middleware will require 2FA verification\n",[235,1336,1337,1341,1353,1361,1366,1375,1384,1393,1426,1431,1435,1439,1443,1449,1453,1458],{"__ignoreMap":233},[238,1338,1339],{"class":240,"line":241},[238,1340,245],{"class":244},[238,1342,1343,1345,1347,1349,1351],{"class":240,"line":248},[238,1344,252],{"class":251},[238,1346,255],{"class":251},[238,1348,259],{"class":258},[238,1350,263],{"class":262},[238,1352,267],{"class":266},[238,1354,1355,1357,1359],{"class":240,"line":270},[238,1356,274],{"class":273},[238,1358,277],{"class":266},[238,1360,280],{"class":266},[238,1362,1363],{"class":240,"line":283},[238,1364,1365],{"class":244},"    \u002F\u002F 2FA endpoint configured\n",[238,1367,1368,1371,1373],{"class":240,"line":304},[238,1369,1370],{"class":273},"    strategies",[238,1372,277],{"class":266},[238,1374,280],{"class":266},[238,1376,1377,1380,1382],{"class":240,"line":322},[238,1378,1379],{"class":273},"      password",[238,1381,277],{"class":266},[238,1383,280],{"class":266},[238,1385,1386,1389,1391],{"class":240,"line":328},[238,1387,1388],{"class":273},"        endpoints",[238,1390,277],{"class":266},[238,1392,280],{"class":266},[238,1394,1395,1398,1400,1402,1404,1406,1408,1410,1412,1414,1416,1418,1420,1422,1424],{"class":240,"line":472},[238,1396,1397],{"class":273},"          twoFactor",[238,1399,277],{"class":266},[238,1401,390],{"class":266},[238,1403,896],{"class":273},[238,1405,277],{"class":266},[238,1407,291],{"class":266},[238,1409,978],{"class":294},[238,1411,298],{"class":266},[238,1413,467],{"class":266},[238,1415,910],{"class":273},[238,1417,277],{"class":266},[238,1419,291],{"class":266},[238,1421,917],{"class":294},[238,1423,298],{"class":266},[238,1425,511],{"class":266},[238,1427,1428],{"class":240,"line":489},[238,1429,1430],{"class":266},"        }\n",[238,1432,1433],{"class":240,"line":514},[238,1434,1049],{"class":266},[238,1436,1437],{"class":240,"line":642},[238,1438,1118],{"class":266},[238,1440,1441],{"class":240,"line":1046},[238,1442,325],{"class":266},[238,1444,1445,1447],{"class":240,"line":1052},[238,1446,331],{"class":266},[238,1448,334],{"class":262},[238,1450,1451],{"class":240,"line":1058},[238,1452,413],{"emptyLinePlaceholder":412},[238,1454,1455],{"class":240,"line":1068},[238,1456,1457],{"class":244},"\u002F\u002F Middleware is automatically registered\n",[238,1459,1460],{"class":240,"line":1084},[238,1461,1462],{"class":244},"\u002F\u002F Routes with twoFactor middleware will require 2FA verification\n",[371,1464,1466],{"id":1465},"manual-2fa-verification","Manual 2FA Verification",[228,1468,1470],{"className":230,"code":1469,"language":232,"meta":233,"style":233},"const { $auth } = useNuxtApp()\n\n\u002F\u002F Verify 2FA code\nconst result = await $auth.twoFactor('password', '123456')\n\nif (result.success) {\n  \u002F\u002F 2FA verified, user authenticated\n  navigateTo('\u002Fdashboard')\n} else {\n  \u002F\u002F Invalid code\n  showError('Invalid 2FA code')\n}\n",[235,1471,1472,1490,1494,1499,1537,1541,1555,1560,1576,1585,1590,1606],{"__ignoreMap":233},[238,1473,1474,1476,1478,1481,1483,1485,1488],{"class":240,"line":241},[238,1475,443],{"class":442},[238,1477,390],{"class":266},[238,1479,1480],{"class":262}," $auth ",[238,1482,331],{"class":266},[238,1484,745],{"class":266},[238,1486,1487],{"class":258}," useNuxtApp",[238,1489,428],{"class":262},[238,1491,1492],{"class":240,"line":248},[238,1493,413],{"emptyLinePlaceholder":412},[238,1495,1496],{"class":240,"line":270},[238,1497,1498],{"class":244},"\u002F\u002F Verify 2FA code\n",[238,1500,1501,1503,1506,1508,1510,1513,1515,1517,1519,1521,1524,1526,1528,1530,1533,1535],{"class":240,"line":283},[238,1502,443],{"class":442},[238,1504,1505],{"class":262}," result ",[238,1507,449],{"class":266},[238,1509,452],{"class":251},[238,1511,1512],{"class":262}," $auth",[238,1514,581],{"class":266},[238,1516,1232],{"class":258},[238,1518,263],{"class":262},[238,1520,298],{"class":266},[238,1522,1523],{"class":294},"password",[238,1525,298],{"class":266},[238,1527,467],{"class":266},[238,1529,291],{"class":266},[238,1531,1532],{"class":294},"123456",[238,1534,298],{"class":266},[238,1536,334],{"class":262},[238,1538,1539],{"class":240,"line":304},[238,1540,413],{"emptyLinePlaceholder":412},[238,1542,1543,1545,1548,1550,1553],{"class":240,"line":322},[238,1544,722],{"class":251},[238,1546,1547],{"class":262}," (result",[238,1549,581],{"class":266},[238,1551,1552],{"class":262},"success) ",[238,1554,267],{"class":266},[238,1556,1557],{"class":240,"line":328},[238,1558,1559],{"class":244},"  \u002F\u002F 2FA verified, user authenticated\n",[238,1561,1562,1565,1567,1569,1572,1574],{"class":240,"line":472},[238,1563,1564],{"class":258},"  navigateTo",[238,1566,263],{"class":273},[238,1568,298],{"class":266},[238,1570,1571],{"class":294},"\u002Fdashboard",[238,1573,298],{"class":266},[238,1575,334],{"class":273},[238,1577,1578,1580,1583],{"class":240,"line":489},[238,1579,331],{"class":266},[238,1581,1582],{"class":251}," else",[238,1584,280],{"class":266},[238,1586,1587],{"class":240,"line":514},[238,1588,1589],{"class":244},"  \u002F\u002F Invalid code\n",[238,1591,1592,1595,1597,1599,1602,1604],{"class":240,"line":642},[238,1593,1594],{"class":258},"  showError",[238,1596,263],{"class":273},[238,1598,298],{"class":266},[238,1600,1601],{"class":294},"Invalid 2FA code",[238,1603,298],{"class":266},[238,1605,334],{"class":273},[238,1607,1608],{"class":240,"line":1046},[238,1609,705],{"class":266},[371,1611,1613],{"id":1612},"_2fa-in-components","2FA in Components",[228,1615,1619],{"className":1616,"code":1617,"language":1618,"meta":233,"style":233},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nconst { $auth } = useNuxtApp()\nconst code = ref('')\n\nconst verify2FA = async () => {\n  const result = await $auth.twoFactor('password', code.value)\n  \n  if (result.success) {\n    await navigateTo('\u002Fdashboard')\n  } else {\n    alert('Invalid code')\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"verify2FA\">\n    \u003Cinput v-model=\"code\" type=\"text\" placeholder=\"Enter 2FA code\" \u002F>\n    \u003Cbutton type=\"submit\">Verify\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n","vue",[235,1620,1621,1648,1664,1683,1687,1707,1744,1749,1770,1788,1797,1813,1817,1821,1830,1834,1843,1865,1911,1941,1950],{"__ignoreMap":233},[238,1622,1623,1626,1629,1632,1635,1637,1640,1643,1645],{"class":240,"line":241},[238,1624,1625],{"class":266},"\u003C",[238,1627,1628],{"class":273},"script",[238,1630,1631],{"class":442}," setup",[238,1633,1634],{"class":442}," lang",[238,1636,449],{"class":266},[238,1638,1639],{"class":266},"\"",[238,1641,1642],{"class":294},"ts",[238,1644,1639],{"class":266},[238,1646,1647],{"class":266},">\n",[238,1649,1650,1652,1654,1656,1658,1660,1662],{"class":240,"line":248},[238,1651,443],{"class":442},[238,1653,390],{"class":266},[238,1655,1480],{"class":262},[238,1657,331],{"class":266},[238,1659,745],{"class":266},[238,1661,1487],{"class":258},[238,1663,428],{"class":262},[238,1665,1666,1668,1671,1673,1676,1678,1681],{"class":240,"line":270},[238,1667,443],{"class":442},[238,1669,1670],{"class":262}," code ",[238,1672,449],{"class":266},[238,1674,1675],{"class":258}," ref",[238,1677,263],{"class":262},[238,1679,1680],{"class":266},"''",[238,1682,334],{"class":262},[238,1684,1685],{"class":240,"line":283},[238,1686,413],{"emptyLinePlaceholder":412},[238,1688,1689,1691,1694,1696,1699,1702,1705],{"class":240,"line":304},[238,1690,443],{"class":442},[238,1692,1693],{"class":262}," verify2FA ",[238,1695,449],{"class":266},[238,1697,1698],{"class":442}," async",[238,1700,1701],{"class":266}," ()",[238,1703,1704],{"class":442}," =>",[238,1706,280],{"class":266},[238,1708,1709,1712,1715,1717,1719,1721,1723,1725,1727,1729,1731,1733,1735,1738,1740,1742],{"class":240,"line":322},[238,1710,1711],{"class":442},"  const",[238,1713,1714],{"class":262}," result",[238,1716,745],{"class":266},[238,1718,452],{"class":251},[238,1720,1512],{"class":262},[238,1722,581],{"class":266},[238,1724,1232],{"class":258},[238,1726,263],{"class":273},[238,1728,298],{"class":266},[238,1730,1523],{"class":294},[238,1732,298],{"class":266},[238,1734,467],{"class":266},[238,1736,1737],{"class":262}," code",[238,1739,581],{"class":266},[238,1741,506],{"class":262},[238,1743,334],{"class":273},[238,1745,1746],{"class":240,"line":328},[238,1747,1748],{"class":273},"  \n",[238,1750,1751,1754,1757,1760,1762,1765,1768],{"class":240,"line":472},[238,1752,1753],{"class":251},"  if",[238,1755,1756],{"class":273}," (",[238,1758,1759],{"class":262},"result",[238,1761,581],{"class":266},[238,1763,1764],{"class":262},"success",[238,1766,1767],{"class":273},") ",[238,1769,267],{"class":266},[238,1771,1772,1775,1778,1780,1782,1784,1786],{"class":240,"line":489},[238,1773,1774],{"class":251},"    await",[238,1776,1777],{"class":258}," navigateTo",[238,1779,263],{"class":273},[238,1781,298],{"class":266},[238,1783,1571],{"class":294},[238,1785,298],{"class":266},[238,1787,334],{"class":273},[238,1789,1790,1793,1795],{"class":240,"line":514},[238,1791,1792],{"class":266},"  }",[238,1794,1582],{"class":251},[238,1796,280],{"class":266},[238,1798,1799,1802,1804,1806,1809,1811],{"class":240,"line":642},[238,1800,1801],{"class":258},"    alert",[238,1803,263],{"class":273},[238,1805,298],{"class":266},[238,1807,1808],{"class":294},"Invalid code",[238,1810,298],{"class":266},[238,1812,334],{"class":273},[238,1814,1815],{"class":240,"line":1046},[238,1816,325],{"class":266},[238,1818,1819],{"class":240,"line":1052},[238,1820,705],{"class":266},[238,1822,1823,1826,1828],{"class":240,"line":1058},[238,1824,1825],{"class":266},"\u003C\u002F",[238,1827,1628],{"class":273},[238,1829,1647],{"class":266},[238,1831,1832],{"class":240,"line":1068},[238,1833,413],{"emptyLinePlaceholder":412},[238,1835,1836,1838,1841],{"class":240,"line":1084},[238,1837,1625],{"class":266},[238,1839,1840],{"class":273},"template",[238,1842,1647],{"class":266},[238,1844,1845,1848,1851,1854,1856,1858,1861,1863],{"class":240,"line":1101},[238,1846,1847],{"class":266},"  \u003C",[238,1849,1850],{"class":273},"form",[238,1852,1853],{"class":442}," @submit.prevent",[238,1855,449],{"class":266},[238,1857,1639],{"class":266},[238,1859,1860],{"class":294},"verify2FA",[238,1862,1639],{"class":266},[238,1864,1647],{"class":266},[238,1866,1867,1870,1873,1876,1878,1880,1882,1884,1887,1889,1891,1894,1896,1899,1901,1903,1906,1908],{"class":240,"line":1115},[238,1868,1869],{"class":266},"    \u003C",[238,1871,1872],{"class":273},"input",[238,1874,1875],{"class":442}," v-model",[238,1877,449],{"class":266},[238,1879,1639],{"class":266},[238,1881,235],{"class":294},[238,1883,1639],{"class":266},[238,1885,1886],{"class":442}," type",[238,1888,449],{"class":266},[238,1890,1639],{"class":266},[238,1892,1893],{"class":294},"text",[238,1895,1639],{"class":266},[238,1897,1898],{"class":442}," placeholder",[238,1900,449],{"class":266},[238,1902,1639],{"class":266},[238,1904,1905],{"class":294},"Enter 2FA code",[238,1907,1639],{"class":266},[238,1909,1910],{"class":266}," \u002F>\n",[238,1912,1913,1915,1918,1920,1922,1924,1927,1929,1932,1935,1937,1939],{"class":240,"line":1121},[238,1914,1869],{"class":266},[238,1916,1917],{"class":273},"button",[238,1919,1886],{"class":442},[238,1921,449],{"class":266},[238,1923,1639],{"class":266},[238,1925,1926],{"class":294},"submit",[238,1928,1639],{"class":266},[238,1930,1931],{"class":266},">",[238,1933,1934],{"class":262},"Verify",[238,1936,1825],{"class":266},[238,1938,1917],{"class":273},[238,1940,1647],{"class":266},[238,1942,1943,1946,1948],{"class":240,"line":1126},[238,1944,1945],{"class":266},"  \u003C\u002F",[238,1947,1850],{"class":273},[238,1949,1647],{"class":266},[238,1951,1953,1955,1957],{"class":240,"line":1952},21,[238,1954,1825],{"class":266},[238,1956,1840],{"class":273},[238,1958,1647],{"class":266},[213,1960,1962],{"id":1961},"_2fa-redirects","2FA Redirects",[176,1964,1965],{},"Configure where users are redirected during 2FA flow:",[228,1967,1969],{"className":230,"code":1968,"language":232,"meta":233,"style":233},"redirect: {\n  login: '\u002Flogin',\n  logout: '\u002F',\n  twoFactor: '\u002F2fa',  \u002F\u002F Redirect to 2FA page when needed\n  home: '\u002Fdashboard'\n}\n",[235,1970,1971,1980,1995,2010,2028,2041],{"__ignoreMap":233},[238,1972,1973,1976,1978],{"class":240,"line":241},[238,1974,1975],{"class":664},"redirect",[238,1977,277],{"class":266},[238,1979,280],{"class":266},[238,1981,1982,1985,1987,1989,1991,1993],{"class":240,"line":248},[238,1983,1984],{"class":664},"  login",[238,1986,277],{"class":266},[238,1988,291],{"class":266},[238,1990,1077],{"class":294},[238,1992,298],{"class":266},[238,1994,301],{"class":266},[238,1996,1997,2000,2002,2004,2006,2008],{"class":240,"line":270},[238,1998,1999],{"class":664},"  logout",[238,2001,277],{"class":266},[238,2003,291],{"class":266},[238,2005,1094],{"class":294},[238,2007,298],{"class":266},[238,2009,301],{"class":266},[238,2011,2012,2015,2017,2019,2021,2023,2025],{"class":240,"line":283},[238,2013,2014],{"class":664},"  twoFactor",[238,2016,277],{"class":266},[238,2018,291],{"class":266},[238,2020,1110],{"class":294},[238,2022,298],{"class":266},[238,2024,467],{"class":266},[238,2026,2027],{"class":244},"  \u002F\u002F Redirect to 2FA page when needed\n",[238,2029,2030,2033,2035,2037,2039],{"class":240,"line":304},[238,2031,2032],{"class":664},"  home",[238,2034,277],{"class":266},[238,2036,291],{"class":266},[238,2038,1571],{"class":294},[238,2040,407],{"class":266},[238,2042,2043],{"class":240,"line":322},[238,2044,705],{"class":266},[213,2046,2048],{"id":2047},"_2fa-middleware","2FA Middleware",[176,2050,2051],{},"The 2FA middleware is automatically registered when you configure a twoFactor endpoint:",[228,2053,2055],{"className":230,"code":2054,"language":232,"meta":233,"style":233},"\u002F\u002F Automatically registered\naddRouteMiddleware({\n  name: 'umbu:two-factor',\n  path: resolve('.\u002Fruntime\u002F' + provider + '\u002Fmiddleware\u002FtwoFactor')\n})\n",[235,2056,2057,2062,2071,2087,2124],{"__ignoreMap":233},[238,2058,2059],{"class":240,"line":241},[238,2060,2061],{"class":244},"\u002F\u002F Automatically registered\n",[238,2063,2064,2067,2069],{"class":240,"line":248},[238,2065,2066],{"class":258},"addRouteMiddleware",[238,2068,263],{"class":262},[238,2070,267],{"class":266},[238,2072,2073,2076,2078,2080,2083,2085],{"class":240,"line":270},[238,2074,2075],{"class":273},"  name",[238,2077,277],{"class":266},[238,2079,291],{"class":266},[238,2081,2082],{"class":294},"umbu:two-factor",[238,2084,298],{"class":266},[238,2086,301],{"class":266},[238,2088,2089,2092,2094,2097,2099,2101,2104,2106,2109,2112,2115,2117,2120,2122],{"class":240,"line":283},[238,2090,2091],{"class":273},"  path",[238,2093,277],{"class":266},[238,2095,2096],{"class":258}," resolve",[238,2098,263],{"class":262},[238,2100,298],{"class":266},[238,2102,2103],{"class":294},".\u002Fruntime\u002F",[238,2105,298],{"class":266},[238,2107,2108],{"class":266}," +",[238,2110,2111],{"class":262}," provider ",[238,2113,2114],{"class":266},"+",[238,2116,291],{"class":266},[238,2118,2119],{"class":294},"\u002Fmiddleware\u002FtwoFactor",[238,2121,298],{"class":266},[238,2123,334],{"class":262},[238,2125,2126,2128],{"class":240,"line":304},[238,2127,331],{"class":266},[238,2129,334],{"class":262},[371,2131,2133],{"id":2132},"using-2fa-middleware","Using 2FA Middleware",[228,2135,2137],{"className":1616,"code":2136,"language":1618,"meta":233,"style":233},"\u003Cscript setup>\n\u002F\u002F Protect route with 2FA middleware\ndefinePageMeta({\n  middleware: ['umbu:two-factor']\n})\n\u003C\u002Fscript>\n",[235,2138,2139,2149,2154,2163,2182,2188],{"__ignoreMap":233},[238,2140,2141,2143,2145,2147],{"class":240,"line":241},[238,2142,1625],{"class":266},[238,2144,1628],{"class":273},[238,2146,1631],{"class":442},[238,2148,1647],{"class":266},[238,2150,2151],{"class":240,"line":248},[238,2152,2153],{"class":244},"\u002F\u002F Protect route with 2FA middleware\n",[238,2155,2156,2159,2161],{"class":240,"line":270},[238,2157,2158],{"class":258},"definePageMeta",[238,2160,263],{"class":262},[238,2162,267],{"class":266},[238,2164,2165,2168,2170,2173,2175,2177,2179],{"class":240,"line":283},[238,2166,2167],{"class":273},"  middleware",[238,2169,277],{"class":266},[238,2171,2172],{"class":262}," [",[238,2174,298],{"class":266},[238,2176,2082],{"class":294},[238,2178,298],{"class":266},[238,2180,2181],{"class":262},"]\n",[238,2183,2184,2186],{"class":240,"line":304},[238,2185,331],{"class":266},[238,2187,334],{"class":262},[238,2189,2190,2192,2194],{"class":240,"line":322},[238,2191,1825],{"class":266},[238,2193,1628],{"class":273},[238,2195,1647],{"class":266},[180,2197,2199],{"id":2198},"security-best-practices","Security Best Practices",[213,2201,196],{"id":2202},"csrf-protection-1",[340,2204,2205,2239,2283],{},[191,2206,2207,2210],{},[194,2208,2209],{},"Always enable CSRF in production",[228,2211,2213],{"className":230,"code":2212,"language":232,"meta":233,"style":233},"auth: {\n  csrf: '\u002Fsanctum\u002Fcsrf-cookie'\n}\n",[235,2214,2215,2223,2235],{"__ignoreMap":233},[238,2216,2217,2219,2221],{"class":240,"line":241},[238,2218,112],{"class":664},[238,2220,277],{"class":266},[238,2222,280],{"class":266},[238,2224,2225,2227,2229,2231,2233],{"class":240,"line":248},[238,2226,688],{"class":664},[238,2228,277],{"class":266},[238,2230,291],{"class":266},[238,2232,314],{"class":294},[238,2234,407],{"class":266},[238,2236,2237],{"class":240,"line":270},[238,2238,705],{"class":266},[191,2240,2241,2244],{},[194,2242,2243],{},"Use HTTPS in production",[228,2245,2247],{"className":230,"code":2246,"language":232,"meta":233,"style":233},"cookie: {\n  options: {\n    secure: true\n  }\n}\n",[235,2248,2249,2257,2265,2275,2279],{"__ignoreMap":233},[238,2250,2251,2253,2255],{"class":240,"line":241},[238,2252,737],{"class":664},[238,2254,277],{"class":266},[238,2256,280],{"class":266},[238,2258,2259,2261,2263],{"class":240,"line":248},[238,2260,732],{"class":664},[238,2262,277],{"class":266},[238,2264,280],{"class":266},[238,2266,2267,2270,2272],{"class":240,"line":270},[238,2268,2269],{"class":664},"    secure",[238,2271,277],{"class":266},[238,2273,2274],{"class":775}," true\n",[238,2276,2277],{"class":240,"line":283},[238,2278,325],{"class":266},[238,2280,2281],{"class":240,"line":304},[238,2282,705],{"class":266},[191,2284,2285,2288],{},[194,2286,2287],{},"Validate CSRF on server",[188,2289,2290,2293],{},[191,2291,2292],{},"Ensure your backend validates CSRF tokens",[191,2294,2295],{},"Use Sanctum's built-in CSRF protection",[213,2297,2299],{"id":2298},"_2fa-implementation","2FA Implementation",[340,2301,2302,2318,2331,2344],{},[191,2303,2304,2307],{},[194,2305,2306],{},"Use secure 2FA methods",[188,2308,2309,2312,2315],{},[191,2310,2311],{},"TOTP (Time-based One-Time Password)",[191,2313,2314],{},"SMS codes (with rate limiting)",[191,2316,2317],{},"Hardware tokens",[191,2319,2320,2323],{},[194,2321,2322],{},"Implement rate limiting",[188,2324,2325,2328],{},[191,2326,2327],{},"Limit 2FA attempts",[191,2329,2330],{},"Lock accounts after failed attempts",[191,2332,2333,2336],{},[194,2334,2335],{},"Backup codes",[188,2337,2338,2341],{},[191,2339,2340],{},"Provide backup recovery codes",[191,2342,2343],{},"Allow secure code regeneration",[191,2345,2346,2349],{},[194,2347,2348],{},"Session management",[188,2350,2351,2354],{},[191,2352,2353],{},"Remember 2FA for trusted devices",[191,2355,2356],{},"Require re-verification for sensitive actions",[213,2358,2360],{"id":2359},"cookie-security","Cookie Security",[340,2362,2363,2449,2500],{},[191,2364,2365,2368],{},[194,2366,2367],{},"Use secure cookie settings in production",[228,2369,2371],{"className":230,"code":2370,"language":232,"meta":233,"style":233},"cookie: {\n  prefix: '__Secure-',\n  options: {\n    httpOnly: true,\n    secure: true,\n    sameSite: 'Strict'\n  }\n}\n",[235,2372,2373,2381,2397,2405,2417,2427,2441,2445],{"__ignoreMap":233},[238,2374,2375,2377,2379],{"class":240,"line":241},[238,2376,737],{"class":664},[238,2378,277],{"class":266},[238,2380,280],{"class":266},[238,2382,2383,2386,2388,2390,2393,2395],{"class":240,"line":248},[238,2384,2385],{"class":664},"  prefix",[238,2387,277],{"class":266},[238,2389,291],{"class":266},[238,2391,2392],{"class":294},"__Secure-",[238,2394,298],{"class":266},[238,2396,301],{"class":266},[238,2398,2399,2401,2403],{"class":240,"line":270},[238,2400,732],{"class":664},[238,2402,277],{"class":266},[238,2404,280],{"class":266},[238,2406,2407,2410,2412,2415],{"class":240,"line":283},[238,2408,2409],{"class":664},"    httpOnly",[238,2411,277],{"class":266},[238,2413,2414],{"class":775}," true",[238,2416,301],{"class":266},[238,2418,2419,2421,2423,2425],{"class":240,"line":304},[238,2420,2269],{"class":664},[238,2422,277],{"class":266},[238,2424,2414],{"class":775},[238,2426,301],{"class":266},[238,2428,2429,2432,2434,2436,2439],{"class":240,"line":322},[238,2430,2431],{"class":664},"    sameSite",[238,2433,277],{"class":266},[238,2435,291],{"class":266},[238,2437,2438],{"class":294},"Strict",[238,2440,407],{"class":266},[238,2442,2443],{"class":240,"line":328},[238,2444,325],{"class":266},[238,2446,2447],{"class":240,"line":472},[238,2448,705],{"class":266},[191,2450,2451,2454],{},[194,2452,2453],{},"Set appropriate expiration",[228,2455,2457],{"className":230,"code":2456,"language":232,"meta":233,"style":233},"options: {\n  maxAge: 60 * 60 * 24 * 7  \u002F\u002F 7 days\n}\n",[235,2458,2459,2467,2496],{"__ignoreMap":233},[238,2460,2461,2463,2465],{"class":240,"line":241},[238,2462,765],{"class":664},[238,2464,277],{"class":266},[238,2466,280],{"class":266},[238,2468,2469,2472,2474,2478,2481,2483,2485,2488,2490,2493],{"class":240,"line":248},[238,2470,2471],{"class":664},"  maxAge",[238,2473,277],{"class":266},[238,2475,2477],{"class":2476},"sbssI"," 60",[238,2479,2480],{"class":266}," *",[238,2482,2477],{"class":2476},[238,2484,2480],{"class":266},[238,2486,2487],{"class":2476}," 24",[238,2489,2480],{"class":266},[238,2491,2492],{"class":2476}," 7",[238,2494,2495],{"class":244},"  \u002F\u002F 7 days\n",[238,2497,2498],{"class":240,"line":270},[238,2499,705],{"class":266},[191,2501,2502,2505],{},[194,2503,2504],{},"Use proper prefixes",[188,2506,2507,2512],{},[191,2508,2509,2511],{},[235,2510,2392],{}," for production",[191,2513,2514,2517],{},[235,2515,2516],{},"__Host-"," for strict security",[180,2519,2521],{"id":2520},"common-security-issues","Common Security Issues",[213,2523,2525],{"id":2524},"csrf-token-missing","CSRF Token Missing",[176,2527,2528,2531],{},[194,2529,2530],{},"Problem",": CSRF token not included in requests",[176,2533,2534,277],{},[194,2535,2536],{},"Solution",[228,2538,2540],{"className":230,"code":2539,"language":232,"meta":233,"style":233},"import { ensureCsrf } from '#auth-utils'\n\n\u002F\u002F Ensure CSRF token before requests\nawait ensureCsrf()\n",[235,2541,2542,2560,2564,2569],{"__ignoreMap":233},[238,2543,2544,2546,2548,2550,2552,2554,2556,2558],{"class":240,"line":241},[238,2545,387],{"class":251},[238,2547,390],{"class":266},[238,2549,393],{"class":262},[238,2551,396],{"class":266},[238,2553,399],{"class":251},[238,2555,291],{"class":266},[238,2557,404],{"class":294},[238,2559,407],{"class":266},[238,2561,2562],{"class":240,"line":248},[238,2563,413],{"emptyLinePlaceholder":412},[238,2565,2566],{"class":240,"line":270},[238,2567,2568],{"class":244},"\u002F\u002F Ensure CSRF token before requests\n",[238,2570,2571,2573,2575],{"class":240,"line":283},[238,2572,423],{"class":251},[238,2574,393],{"class":258},[238,2576,428],{"class":262},[213,2578,2580],{"id":2579},"_2fa-not-working","2FA Not Working",[176,2582,2583,2585],{},[194,2584,2530],{},": 2FA verification fails",[176,2587,2588,277],{},[194,2589,2536],{},[340,2591,2592,2595,2598,2601],{},[191,2593,2594],{},"Verify endpoint configuration",[191,2596,2597],{},"Check response property names",[191,2599,2600],{},"Ensure header name matches backend expectations",[191,2602,2603],{},"Verify code format (6 digits, etc.)",[213,2605,2607],{"id":2606},"cookie-security-issues","Cookie Security Issues",[176,2609,2610,2612],{},[194,2611,2530],{},": Cookies not secure in production",[176,2614,2615,277],{},[194,2616,2536],{},[228,2618,2620],{"className":230,"code":2619,"language":232,"meta":233,"style":233},"cookie: {\n  prefix: '__Secure-',\n  options: {\n    secure: true,\n    httpOnly: true,\n    sameSite: 'Strict'\n  }\n}\n",[235,2621,2622,2630,2644,2652,2662,2672,2684,2688],{"__ignoreMap":233},[238,2623,2624,2626,2628],{"class":240,"line":241},[238,2625,737],{"class":664},[238,2627,277],{"class":266},[238,2629,280],{"class":266},[238,2631,2632,2634,2636,2638,2640,2642],{"class":240,"line":248},[238,2633,2385],{"class":664},[238,2635,277],{"class":266},[238,2637,291],{"class":266},[238,2639,2392],{"class":294},[238,2641,298],{"class":266},[238,2643,301],{"class":266},[238,2645,2646,2648,2650],{"class":240,"line":270},[238,2647,732],{"class":664},[238,2649,277],{"class":266},[238,2651,280],{"class":266},[238,2653,2654,2656,2658,2660],{"class":240,"line":283},[238,2655,2269],{"class":664},[238,2657,277],{"class":266},[238,2659,2414],{"class":775},[238,2661,301],{"class":266},[238,2663,2664,2666,2668,2670],{"class":240,"line":304},[238,2665,2409],{"class":664},[238,2667,277],{"class":266},[238,2669,2414],{"class":775},[238,2671,301],{"class":266},[238,2673,2674,2676,2678,2680,2682],{"class":240,"line":322},[238,2675,2431],{"class":664},[238,2677,277],{"class":266},[238,2679,291],{"class":266},[238,2681,2438],{"class":294},[238,2683,407],{"class":266},[238,2685,2686],{"class":240,"line":328},[238,2687,325],{"class":266},[238,2689,2690],{"class":240,"line":472},[238,2691,705],{"class":266},[180,2693,2695],{"id":2694},"testing-security-features","Testing Security Features",[213,2697,2699],{"id":2698},"testing-csrf","Testing CSRF",[228,2701,2703],{"className":230,"code":2702,"language":232,"meta":233,"style":233},"\u002F\u002F test\u002Fcsrf.test.ts\nimport { describe, it, expect } from 'vitest'\nimport { ensureCsrf } from '#auth-utils'\n\ndescribe('CSRF Protection', () => {\n  it('should fetch CSRF token', async () => {\n    await ensureCsrf()\n    \u002F\u002F Verify token is present\n  })\n})\n",[235,2704,2705,2710,2740,2758,2762,2783,2807,2815,2820,2826],{"__ignoreMap":233},[238,2706,2707],{"class":240,"line":241},[238,2708,2709],{"class":244},"\u002F\u002F test\u002Fcsrf.test.ts\n",[238,2711,2712,2714,2716,2719,2721,2724,2726,2729,2731,2733,2735,2738],{"class":240,"line":248},[238,2713,387],{"class":251},[238,2715,390],{"class":266},[238,2717,2718],{"class":262}," describe",[238,2720,467],{"class":266},[238,2722,2723],{"class":262}," it",[238,2725,467],{"class":266},[238,2727,2728],{"class":262}," expect",[238,2730,396],{"class":266},[238,2732,399],{"class":251},[238,2734,291],{"class":266},[238,2736,2737],{"class":294},"vitest",[238,2739,407],{"class":266},[238,2741,2742,2744,2746,2748,2750,2752,2754,2756],{"class":240,"line":270},[238,2743,387],{"class":251},[238,2745,390],{"class":266},[238,2747,393],{"class":262},[238,2749,396],{"class":266},[238,2751,399],{"class":251},[238,2753,291],{"class":266},[238,2755,404],{"class":294},[238,2757,407],{"class":266},[238,2759,2760],{"class":240,"line":283},[238,2761,413],{"emptyLinePlaceholder":412},[238,2763,2764,2767,2769,2771,2773,2775,2777,2779,2781],{"class":240,"line":304},[238,2765,2766],{"class":258},"describe",[238,2768,263],{"class":262},[238,2770,298],{"class":266},[238,2772,196],{"class":294},[238,2774,298],{"class":266},[238,2776,467],{"class":266},[238,2778,1701],{"class":266},[238,2780,1704],{"class":442},[238,2782,280],{"class":266},[238,2784,2785,2788,2790,2792,2795,2797,2799,2801,2803,2805],{"class":240,"line":322},[238,2786,2787],{"class":258},"  it",[238,2789,263],{"class":273},[238,2791,298],{"class":266},[238,2793,2794],{"class":294},"should fetch CSRF token",[238,2796,298],{"class":266},[238,2798,467],{"class":266},[238,2800,1698],{"class":442},[238,2802,1701],{"class":266},[238,2804,1704],{"class":442},[238,2806,280],{"class":266},[238,2808,2809,2811,2813],{"class":240,"line":328},[238,2810,1774],{"class":251},[238,2812,393],{"class":258},[238,2814,428],{"class":273},[238,2816,2817],{"class":240,"line":472},[238,2818,2819],{"class":244},"    \u002F\u002F Verify token is present\n",[238,2821,2822,2824],{"class":240,"line":489},[238,2823,1792],{"class":266},[238,2825,334],{"class":273},[238,2827,2828,2830],{"class":240,"line":514},[238,2829,331],{"class":266},[238,2831,334],{"class":262},[213,2833,2835],{"id":2834},"testing-2fa","Testing 2FA",[228,2837,2839],{"className":230,"code":2838,"language":232,"meta":233,"style":233},"\u002F\u002F test\u002F2fa.test.ts\nimport { describe, it, expect } from 'vitest'\n\ndescribe('2FA', () => {\n  it('should verify 2FA code', async () => {\n    const { $auth } = useNuxtApp()\n    const result = await $auth.twoFactor('password', '123456')\n    expect(result.success).toBe(true)\n  })\n})\n",[235,2840,2841,2846,2872,2876,2897,2920,2937,2971,2999,3005],{"__ignoreMap":233},[238,2842,2843],{"class":240,"line":241},[238,2844,2845],{"class":244},"\u002F\u002F test\u002F2fa.test.ts\n",[238,2847,2848,2850,2852,2854,2856,2858,2860,2862,2864,2866,2868,2870],{"class":240,"line":248},[238,2849,387],{"class":251},[238,2851,390],{"class":266},[238,2853,2718],{"class":262},[238,2855,467],{"class":266},[238,2857,2723],{"class":262},[238,2859,467],{"class":266},[238,2861,2728],{"class":262},[238,2863,396],{"class":266},[238,2865,399],{"class":251},[238,2867,291],{"class":266},[238,2869,2737],{"class":294},[238,2871,407],{"class":266},[238,2873,2874],{"class":240,"line":270},[238,2875,413],{"emptyLinePlaceholder":412},[238,2877,2878,2880,2882,2884,2887,2889,2891,2893,2895],{"class":240,"line":283},[238,2879,2766],{"class":258},[238,2881,263],{"class":262},[238,2883,298],{"class":266},[238,2885,2886],{"class":294},"2FA",[238,2888,298],{"class":266},[238,2890,467],{"class":266},[238,2892,1701],{"class":266},[238,2894,1704],{"class":442},[238,2896,280],{"class":266},[238,2898,2899,2901,2903,2905,2908,2910,2912,2914,2916,2918],{"class":240,"line":304},[238,2900,2787],{"class":258},[238,2902,263],{"class":273},[238,2904,298],{"class":266},[238,2906,2907],{"class":294},"should verify 2FA code",[238,2909,298],{"class":266},[238,2911,467],{"class":266},[238,2913,1698],{"class":442},[238,2915,1701],{"class":266},[238,2917,1704],{"class":442},[238,2919,280],{"class":266},[238,2921,2922,2925,2927,2929,2931,2933,2935],{"class":240,"line":322},[238,2923,2924],{"class":442},"    const",[238,2926,390],{"class":266},[238,2928,1512],{"class":262},[238,2930,396],{"class":266},[238,2932,745],{"class":266},[238,2934,1487],{"class":258},[238,2936,428],{"class":273},[238,2938,2939,2941,2943,2945,2947,2949,2951,2953,2955,2957,2959,2961,2963,2965,2967,2969],{"class":240,"line":328},[238,2940,2924],{"class":442},[238,2942,1714],{"class":262},[238,2944,745],{"class":266},[238,2946,452],{"class":251},[238,2948,1512],{"class":262},[238,2950,581],{"class":266},[238,2952,1232],{"class":258},[238,2954,263],{"class":273},[238,2956,298],{"class":266},[238,2958,1523],{"class":294},[238,2960,298],{"class":266},[238,2962,467],{"class":266},[238,2964,291],{"class":266},[238,2966,1532],{"class":294},[238,2968,298],{"class":266},[238,2970,334],{"class":273},[238,2972,2973,2976,2978,2980,2982,2984,2987,2989,2992,2994,2997],{"class":240,"line":472},[238,2974,2975],{"class":258},"    expect",[238,2977,263],{"class":273},[238,2979,1759],{"class":262},[238,2981,581],{"class":266},[238,2983,1764],{"class":262},[238,2985,2986],{"class":273},")",[238,2988,581],{"class":266},[238,2990,2991],{"class":258},"toBe",[238,2993,263],{"class":273},[238,2995,2996],{"class":775},"true",[238,2998,334],{"class":273},[238,3000,3001,3003],{"class":240,"line":489},[238,3002,1792],{"class":266},[238,3004,334],{"class":273},[238,3006,3007,3009],{"class":240,"line":514},[238,3008,331],{"class":266},[238,3010,334],{"class":262},[180,3012,3014],{"id":3013},"security-checklist","Security Checklist",[213,3016,3018],{"id":3017},"before-production","Before Production",[188,3020,3023,3031,3037,3043,3049,3055,3061,3067],{"className":3021},[3022],"contains-task-list",[191,3024,3027,3030],{"className":3025},[3026],"task-list-item",[1872,3028],{"disabled":412,"type":3029},"checkbox"," CSRF protection enabled",[191,3032,3034,3036],{"className":3033},[3026],[1872,3035],{"disabled":412,"type":3029}," HTTPS configured",[191,3038,3040,3042],{"className":3039},[3026],[1872,3041],{"disabled":412,"type":3029}," Secure cookie settings",[191,3044,3046,3048],{"className":3045},[3026],[1872,3047],{"disabled":412,"type":3029}," 2FA implemented for sensitive actions",[191,3050,3052,3054],{"className":3051},[3026],[1872,3053],{"disabled":412,"type":3029}," Rate limiting configured",[191,3056,3058,3060],{"className":3057},[3026],[1872,3059],{"disabled":412,"type":3029}," Session management configured",[191,3062,3064,3066],{"className":3063},[3026],[1872,3065],{"disabled":412,"type":3029}," Error handling doesn't leak information",[191,3068,3070,3072],{"className":3069},[3026],[1872,3071],{"disabled":412,"type":3029}," Logging configured for security events",[213,3074,3076],{"id":3075},"regular-security-audits","Regular Security Audits",[188,3078,3080,3086,3092,3098,3104,3110],{"className":3079},[3022],[191,3081,3083,3085],{"className":3082},[3026],[1872,3084],{"disabled":412,"type":3029}," Review dependency updates",[191,3087,3089,3091],{"className":3088},[3026],[1872,3090],{"disabled":412,"type":3029}," Check for security advisories",[191,3093,3095,3097],{"className":3094},[3026],[1872,3096],{"disabled":412,"type":3029}," Audit authentication flows",[191,3099,3101,3103],{"className":3100},[3026],[1872,3102],{"disabled":412,"type":3029}," Test for common vulnerabilities",[191,3105,3107,3109],{"className":3106},[3026],[1872,3108],{"disabled":412,"type":3029}," Review access logs",[191,3111,3113,3115],{"className":3112},[3026],[1872,3114],{"disabled":412,"type":3029}," Update security configurations",[180,3117,3119],{"id":3118},"troubleshooting","Troubleshooting",[213,3121,3123],{"id":3122},"csrf-issues","CSRF Issues",[176,3125,3126],{},[194,3127,3128],{},"CSRF cookie not being set",[340,3130,3131,3134,3137,3140],{},[191,3132,3133],{},"Verify CSRF endpoint is correct",[191,3135,3136],{},"Check browser console for errors",[191,3138,3139],{},"Ensure cookies are enabled",[191,3141,3142],{},"Verify backend CSRF configuration",[176,3144,3145],{},[194,3146,3147],{},"CSRF token validation failing",[340,3149,3150,3153,3156,3159],{},[191,3151,3152],{},"Check token format",[191,3154,3155],{},"Verify header name",[191,3157,3158],{},"Ensure token is included in requests",[191,3160,3161],{},"Check backend validation logic",[213,3163,3165],{"id":3164},"_2fa-issues","2FA Issues",[176,3167,3168],{},[194,3169,3170],{},"2FA middleware not triggering",[340,3172,3173,3176,3179,3182],{},[191,3174,3175],{},"Verify twoFactor endpoint is configured",[191,3177,3178],{},"Check that middleware is registered",[191,3180,3181],{},"Ensure route has middleware applied",[191,3183,3184],{},"Check redirect configuration",[176,3186,3187],{},[194,3188,3189],{},"2FA verification failing",[340,3191,3192,3195,3197,3200],{},[191,3193,3194],{},"Verify endpoint URL and method",[191,3196,2597],{},[191,3198,3199],{},"Ensure code format is correct",[191,3201,3202],{},"Verify header name matches backend",[180,3204,3206],{"id":3205},"additional-security-resources","Additional Security Resources",[188,3208,3209,3218,3225,3232],{},[191,3210,3211],{},[3212,3213,3217],"a",{"href":3214,"rel":3215},"https:\u002F\u002Fcheatsheetseries.owasp.org\u002Fcheatsheets\u002FCross-Site_Request_Forgery_Prevention_Cheat_Sheet.html",[3216],"nofollow","OWASP CSRF Prevention Cheat Sheet",[191,3219,3220],{},[3212,3221,3224],{"href":3222,"rel":3223},"https:\u002F\u002Fcheatsheetseries.owasp.org\u002Fcheatsheets\u002FAuthentication_Cheat_Sheet.html",[3216],"OWASP Authentication Cheat Sheet",[191,3226,3227],{},[3212,3228,3231],{"href":3229,"rel":3230},"https:\u002F\u002Flaravel.com\u002Fdocs\u002Fsanctum",[3216],"Laravel Sanctum Documentation",[191,3233,3234],{},[3212,3235,3238],{"href":3236,"rel":3237},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002Fguide\u002Fsecurity-best-practices",[3216],"Nuxt Security Best Practices",[3240,3241,3242],"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 .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 .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 .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":233,"searchDepth":241,"depth":248,"links":3244},[3245,3246,3254,3262,3267,3272,3276,3280,3284],{"id":182,"depth":248,"text":183},{"id":211,"depth":248,"text":196,"children":3247},[3248,3249,3250,3251,3252,3253],{"id":215,"depth":270,"text":216},{"id":222,"depth":270,"text":223},{"id":337,"depth":270,"text":338},{"id":368,"depth":270,"text":369},{"id":649,"depth":270,"text":650},{"id":783,"depth":270,"text":784},{"id":837,"depth":248,"text":838,"children":3255},[3256,3257,3258,3259,3260,3261],{"id":841,"depth":270,"text":842},{"id":848,"depth":270,"text":849},{"id":1131,"depth":270,"text":1132},{"id":1323,"depth":270,"text":1324},{"id":1961,"depth":270,"text":1962},{"id":2047,"depth":270,"text":2048},{"id":2198,"depth":248,"text":2199,"children":3263},[3264,3265,3266],{"id":2202,"depth":270,"text":196},{"id":2298,"depth":270,"text":2299},{"id":2359,"depth":270,"text":2360},{"id":2520,"depth":248,"text":2521,"children":3268},[3269,3270,3271],{"id":2524,"depth":270,"text":2525},{"id":2579,"depth":270,"text":2580},{"id":2606,"depth":270,"text":2607},{"id":2694,"depth":248,"text":2695,"children":3273},[3274,3275],{"id":2698,"depth":270,"text":2699},{"id":2834,"depth":270,"text":2835},{"id":3013,"depth":248,"text":3014,"children":3277},[3278,3279],{"id":3017,"depth":270,"text":3018},{"id":3075,"depth":270,"text":3076},{"id":3118,"depth":248,"text":3119,"children":3281},[3282,3283],{"id":3122,"depth":270,"text":3123},{"id":3164,"depth":270,"text":3165},{"id":3205,"depth":248,"text":3206},"CSRF protection and two-factor authentication (2FA) implementation","md",null,{},{"icon":37},{"title":162,"description":3285},"cq1ZbICDtfln-l7c2gHk1wzvNNG_jN-ijfhiwM22B34",[3293,3295],{"title":157,"path":158,"stem":159,"description":3294,"icon":160,"children":-1},"Using",{"title":166,"path":167,"stem":168,"description":3296,"icon":169,"children":-1},"Runtime config and secrets management for Nuxt Umbu",1785126615835]