[{"data":1,"prerenderedAt":517},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Ftwo-factor":203,"\u002Fguides\u002Ftwo-factor-surround":512},[4,33,96,114,177],{"title":5,"path":6,"stem":7,"children":8,"icon":32},"Get started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12,17,22,27],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-house",{"title":13,"path":14,"stem":15,"icon":16},"Install AuthEndpoints","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":18,"path":19,"stem":20,"icon":21},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",{"title":23,"path":24,"stem":25,"icon":26},"Choose a sign-in stack","\u002Fgetting-started\u002Fchoose-a-sign-in-stack","1.getting-started\u002F4.choose-a-sign-in-stack","i-lucide-signpost",{"title":28,"path":29,"stem":30,"icon":31},"Use the AuthEndpoints skill with coding agents","\u002Fgetting-started\u002Fai-agents","1.getting-started\u002F5.ai-agents","i-lucide-bot","i-lucide-rocket",{"title":34,"path":35,"stem":36,"children":37,"icon":95},"Guides","\u002Fguides","2.guides\u002F01.index",[38,40,45,50,55,60,65,70,75,80,85,90],{"title":34,"path":35,"stem":36,"icon":39},"i-lucide-list-checks",{"title":41,"path":42,"stem":43,"icon":44},"Register users","\u002Fguides\u002Fregistration","2.guides\u002F02.registration","i-lucide-user-plus",{"title":46,"path":47,"stem":48,"icon":49},"Sign users in","\u002Fguides\u002Fsign-in","2.guides\u002F03.sign-in","i-lucide-log-in",{"title":51,"path":52,"stem":53,"icon":54},"Sign users out","\u002Fguides\u002Fsign-out","2.guides\u002F04.sign-out","i-lucide-log-out",{"title":56,"path":57,"stem":58,"icon":59},"Turn on two-factor authentication","\u002Fguides\u002Ftwo-factor","2.guides\u002F05.two-factor","i-lucide-smartphone",{"title":61,"path":62,"stem":63,"icon":64},"Reset a forgotten password","\u002Fguides\u002Freset-password","2.guides\u002F06.reset-password","i-lucide-key-round",{"title":66,"path":67,"stem":68,"icon":69},"Change a user's email or password","\u002Fguides\u002Fmanage-account","2.guides\u002F07.manage-account","i-lucide-user-cog",{"title":71,"path":72,"stem":73,"icon":74},"Add, rename, and remove passkeys","\u002Fguides\u002Fmanage-passkeys","2.guides\u002F08.manage-passkeys","i-lucide-scan-face",{"title":76,"path":77,"stem":78,"icon":79},"Link and unlink GitHub or Google accounts","\u002Fguides\u002Flink-external-accounts","2.guides\u002F09.link-external-accounts","i-lucide-link",{"title":81,"path":82,"stem":83,"icon":84},"Require step-up before sensitive actions","\u002Fguides\u002Fstep-up","2.guides\u002F10.step-up","i-lucide-shield-check",{"title":86,"path":87,"stem":88,"icon":89},"Call the API from a browser","\u002Fguides\u002Fbrowser-clients","2.guides\u002F11.browser-clients","i-lucide-globe",{"title":91,"path":92,"stem":93,"icon":94},"Prepare for production","\u002Fguides\u002Fproduction","2.guides\u002F12.production","i-lucide-factory","i-lucide-waypoints",{"title":97,"path":98,"stem":99,"children":100,"icon":113},"Composable endpoints","\u002Fcomposables","3.composables\u002F1.index",[101,104,108],{"title":102,"path":98,"stem":99,"icon":103},"How composition works","i-lucide-layout-grid",{"title":105,"path":106,"stem":107,"icon":39},"Composition requirements","\u002Fcomposables\u002Frequirements","3.composables\u002F2.requirements",{"title":109,"path":110,"stem":111,"icon":112},"Compose a custom auth stack","\u002Fcomposables\u002Frecipes","3.composables\u002F3.recipes","i-lucide-book-marked","i-lucide-blocks",{"title":115,"icon":116,"path":117,"stem":118,"children":119,"page":176},"Reference","i-lucide-book-open","\u002Fmodules","4.modules",[120,125,129,134,139,144,148,153,157,162,166,171],{"title":121,"path":122,"stem":123,"icon":124},"Endpoint reference","\u002Fmodules\u002Fendpoints","4.modules\u002F01.endpoints","i-lucide-route",{"title":126,"path":127,"stem":128,"icon":69},"Identity management module","\u002Fmodules\u002Fidentity-management","4.modules\u002F02.identity-management",{"title":130,"path":131,"stem":132,"icon":133},"Cookie sign-in module","\u002Fmodules\u002Fcookie-auth","4.modules\u002F03.cookie-auth","i-lucide-cookie",{"title":135,"path":136,"stem":137,"icon":138},"Identity bearer sign-in module","\u002Fmodules\u002Fbearer-auth","4.modules\u002F04.bearer-auth","i-lucide-key",{"title":140,"path":141,"stem":142,"icon":143},"JWT module","\u002Fmodules\u002Fjwt","4.modules\u002F05.jwt","i-lucide-fingerprint",{"title":145,"path":146,"stem":147,"icon":74},"Passkeys module","\u002Fmodules\u002Fpasskeys","4.modules\u002F06.passkeys",{"title":149,"path":150,"stem":151,"icon":152},"ReAuth module","\u002Fmodules\u002Freauth","4.modules\u002F07.reauth","i-lucide-shield-alert",{"title":154,"path":155,"stem":156,"icon":49},"External OAuth packages","\u002Fmodules\u002Fexternal-oauth","4.modules\u002F08.external-oauth",{"title":158,"path":159,"stem":160,"icon":161},"Configuration options","\u002Fmodules\u002Fconfiguration","4.modules\u002F09.configuration","i-lucide-settings",{"title":163,"path":164,"stem":165,"icon":84},"Antiforgery (CSRF) rules","\u002Fmodules\u002Fcsrf","4.modules\u002F10.csrf",{"title":167,"path":168,"stem":169,"icon":170},"Responses and errors","\u002Fmodules\u002Ferrors","4.modules\u002F11.errors","i-lucide-circle-alert",{"title":172,"path":173,"stem":174,"icon":175},"Rate-limit policies","\u002Fmodules\u002Frate-limits","4.modules\u002F12.rate-limits","i-lucide-gauge",false,{"title":178,"icon":179,"path":180,"stem":181,"children":182,"page":176},"Concepts","i-lucide-lightbulb","\u002Fconcepts","5.concepts",[183,188,193,198],{"title":184,"path":185,"stem":186,"icon":187},"AuthEndpoints compared with other options","\u002Fconcepts\u002Fcompare","5.concepts\u002F1.compare","i-lucide-git-compare",{"title":189,"path":190,"stem":191,"icon":192},"Stock Identity endpoints vs AuthEndpoints","\u002Fconcepts\u002Fstock-identity-vs-authendpoints","5.concepts\u002F2.stock-identity-vs-authendpoints","i-lucide-columns-2",{"title":194,"path":195,"stem":196,"icon":197},"Security model","\u002Fconcepts\u002Fsecurity-model","5.concepts\u002F3.security-model","i-lucide-shield",{"title":199,"path":200,"stem":201,"icon":202},"FAQ","\u002Fconcepts\u002Ffaq","5.concepts\u002F4.faq","i-lucide-circle-help",{"id":204,"title":56,"body":205,"description":505,"extension":506,"links":507,"meta":508,"navigation":509,"path":57,"seo":510,"stem":58,"__hash__":511},"docs\u002F2.guides\u002F05.two-factor.md",{"type":206,"value":207,"toc":493},"minimark",[208,229,248,253,258,262,277,281,336,350,353,371,375,395,402,406,448,458,462,468,472],[209,210,211,212,216,217,220,221,224,225,228],"p",{},"Users manage authenticator (TOTP) two-factor authentication through ",[213,214,215],"code",{},"\u002Fidentity\u002Fmanage\u002F2fa",". ",[213,218,219],{},"POST"," requires a signed-in user, a CSRF token in the ",[213,222,223],{},"RequestVerificationToken"," header, and a fresh ReAuth proof. The body is Identity's ",[213,226,227],{},"TwoFactorRequest",".",[209,230,231,232,235,236,239,240,242,243,228],{},"The steps assume a cookie session. Send ",[213,233,234],{},"credentials: 'include'"," and get a CSRF token from ",[213,237,238],{},"GET \u002Fidentity\u002FcsrfToken"," before each ",[213,241,219],{},". To sign in after 2FA is on, see ",[244,245,247],"a",{"href":246},"\u002Fguides\u002Fsign-in\u002F#enter-a-two-factor-code-or-a-recovery-code","Enter a two-factor code or a recovery code",[249,250,252],"h2",{"id":251},"video","Video",[254,255],"youtube-embed",{"id":256,"title":257},"fY1w3ROcyrE","Two-factor authentication end-to-end",[249,259,261],{"id":260},"read-the-2fa-status","Read the 2FA status",[209,263,264,265,268,269,272,273,276],{},"Send ",[213,266,267],{},"GET \u002Fidentity\u002Fmanage\u002F2fa",". The response is ",[213,270,271],{},"{ \"isTwoFactorEnabled\": true }"," or ",[213,274,275],{},"false",". This route needs no CSRF token and no ReAuth.",[249,278,280],{"id":279},"turn-on-2fa","Turn on 2FA",[282,283,284,291,304,307,314,322],"ol",{},[285,286,287,288,228],"li",{},"Complete step-up. See ",[244,289,81],{"href":290},"\u002Fguides\u002Fstep-up\u002F",[285,292,264,293,296,297,300,301,228],{},[213,294,295],{},"POST \u002Fidentity\u002Fmanage\u002F2fa"," with the body ",[213,298,299],{},"{}",". If the user has no authenticator key, the response includes a new ",[213,302,303],{},"sharedKey",[285,305,306],{},"Show the shared key, or a QR code made from it, so that the user can add it to an authenticator app.",[285,308,309,310,313],{},"If the ReAuth proof expired, complete step-up again. The default lifetime is 5 minutes (",[213,311,312],{},"ReAuth.Lifetime",").",[285,315,264,316,318,319,228],{},[213,317,295],{}," with ",[213,320,321],{},"{ \"enable\": true, \"twoFactorCode\": \"\u003C6-digit code>\" }",[285,323,324,325,328,329,332,333,228],{},"On ",[213,326,327],{},"200",", show the ",[213,330,331],{},"recoveryCodes"," from the response. When the user has no recovery codes left, turning on 2FA issues 10 new codes. The response also has ",[213,334,335],{},"isTwoFactorEnabled: true",[209,337,338,339,342,343,346,347,228],{},"Do not send ",[213,340,341],{},"enable: true"," together with ",[213,344,345],{},"resetSharedKey: true",". That request returns a validation problem with the key ",[213,348,349],{},"CannotResetSharedKeyAndEnable",[209,351,352],{},"These validation problems can also come back from step 5:",[354,355,356,365],"ul",{},[285,357,358,361,362,228],{},[213,359,360],{},"RequiresTwoFactor",": the request had no ",[213,363,364],{},"twoFactorCode",[285,366,367,370],{},[213,368,369],{},"InvalidTwoFactorCode",": the code did not match the shared key.",[249,372,374],{"id":373},"turn-off-2fa","Turn off 2FA",[282,376,377,380,387],{},[285,378,379],{},"Complete step-up.",[285,381,264,382,318,384,228],{},[213,383,295],{},[213,385,386],{},"{ \"enable\": false }",[285,388,324,389,391,392,228],{},[213,390,327],{},", the response has ",[213,393,394],{},"isTwoFactorEnabled: false",[209,396,397,398,401],{},"To rotate the authenticator key, send ",[213,399,400],{},"{ \"resetSharedKey\": true }",". That request also turns 2FA off. Turn it on again with a code from the new key.",[249,403,405],{"id":404},"use-the-other-request-fields","Use the other request fields",[407,408,409,422],"table",{},[410,411,412],"thead",{},[413,414,415,419],"tr",{},[416,417,418],"th",{},"Field",[416,420,421],{},"Effect",[423,424,425,438],"tbody",{},[413,426,427,433],{},[428,429,430],"td",{},[213,431,432],{},"resetRecoveryCodes",[428,434,435,436,228],{},"Issues 10 new recovery codes and returns them in ",[213,437,331],{},[413,439,440,445],{},[428,441,442],{},[213,443,444],{},"forgetMachine",[428,446,447],{},"Clears the two-factor remember-client cookie.",[209,449,450,451,453,454,228],{},"A persistent cookie login with a valid authenticator code sets the remember-client cookie. Later password logins from that browser skip the 2FA challenge until the user sends ",[213,452,444],{}," or logs out. See ",[244,455,457],{"href":456},"\u002Fguides\u002Fsign-in\u002F#remembered-browsers","Remembered browsers",[249,459,461],{"id":460},"know-which-sign-ins-skip-2fa","Know which sign-ins skip 2FA",[209,463,464,465,228],{},"Passkey sign-in and GitHub or Google sign-in do not ask for a 2FA code, even when 2FA is on. See ",[244,466,194],{"href":467},"\u002Fconcepts\u002Fsecurity-model\u002F#two-factor-is-a-password-add-on",[249,469,471],{"id":470},"related","Related",[354,473,474,479,483,488],{},[285,475,476],{},[244,477,46],{"href":478},"\u002Fguides\u002Fsign-in\u002F",[285,480,481],{},[244,482,81],{"href":290},[285,484,485],{},[244,486,126],{"href":487},"\u002Fmodules\u002Fidentity-management\u002F",[285,489,490],{},[244,491,149],{"href":492},"\u002Fmodules\u002Freauth\u002F",{"title":494,"searchDepth":495,"depth":496,"links":497},"",1,2,[498,499,500,501,502,503,504],{"id":251,"depth":496,"text":252},{"id":260,"depth":496,"text":261},{"id":279,"depth":496,"text":280},{"id":373,"depth":496,"text":374},{"id":404,"depth":496,"text":405},{"id":460,"depth":496,"text":461},{"id":470,"depth":496,"text":471},"Turn authenticator two-factor authentication on and off, and issue recovery codes.","md",null,{},{"icon":59},{"title":56,"description":505},"AVZakX_O4H3PUWJmSc_TaX-XODi7Nb5-eDttVOqHQVA",[513,515],{"title":51,"path":52,"stem":53,"description":514,"icon":54,"children":-1},"Sign users out of the cookie, Identity bearer, and JWT stacks.",{"title":61,"path":62,"stem":63,"description":516,"icon":64,"children":-1},"Request a reset mail, set a new password, then sign in.",1791123626678]