[{"data":1,"prerenderedAt":450},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Fproduction":203,"\u002Fguides\u002Fproduction-surround":445},[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":91,"body":205,"description":438,"extension":439,"links":440,"meta":441,"navigation":442,"path":92,"seo":443,"stem":93,"__hash__":444},"docs\u002F2.guides\u002F12.production.md",{"type":206,"value":207,"toc":427},"minimark",[208,212,217,257,261,264,298,302,305,337,341,355,359,405,409],[209,210,211],"p",{},"Work through this checklist before you deploy. Startup validation catches some items. The rest are your responsibility.",[213,214,216],"h2",{"id":215},"check-the-core-settings","Check the core settings",[218,219,220,224,240,247],"ul",{},[221,222,223],"li",{},"Serve the API over HTTPS.",[221,225,226,227,231,232,235,236,239],{},"Register a real ",[228,229,230],"code",{},"IEmailSender\u003CTUser>",". When ",[228,233,234],{},"RequireEmailSenderInProduction"," is ",[228,237,238],{},"true"," (the default), startup fails in Production while Identity's no-op sender is registered.",[221,241,242,243,246],{},"Set ",[228,244,245],{},"Passkeys.ServerDomain"," when passkeys are on (the default). Startup fails in Production without it.",[221,248,249,250,253,254,256],{},"Leave ",[228,251,252],{},"RequireConfirmedAccount"," at ",[228,255,238],{}," unless you have another way to verify email ownership.",[213,258,260],{"id":259},"check-the-jwt-settings","Check the JWT settings",[209,262,263],{},"Skip this section if JWT is off.",[218,265,266,277,288,291],{},[221,267,268,269,272,273,276],{},"Call ",[228,270,271],{},"modelBuilder.UseRefreshToken()"," on your ",[228,274,275],{},"DbContext"," and apply the migration.",[221,278,279,280,283,284,287],{},"Set an issuer and an audience. Startup fails in Production with the library defaults (",[228,281,282],{},"Jwt"," and ",[228,285,286],{},"JwtAudience",").",[221,289,290],{},"Use a symmetric key of at least 256 bits (32 UTF-8 bytes), or an asymmetric key.",[221,292,293,294,297],{},"If you upgrade from plaintext refresh-token storage, recreate the ",[228,295,296],{},"AuthEndpointsRefreshTokens"," table. AuthEndpoints now stores hashed tokens with reuse detection.",[213,299,301],{"id":300},"check-the-external-oauth-settings","Check the external OAuth settings",[209,303,304],{},"Skip this section if you do not use GitHub or Google.",[218,306,307,314,324,330],{},[221,308,309,310,313],{},"Map the OAuth routes yourself. ",[228,311,312],{},"MapAuthEndpoints"," does not map them.",[221,315,316,317,320,321,287],{},"Host a page at ",[228,318,319],{},"ErrorPath"," (default ",[228,322,323],{},"\u002Fauth\u002Fexternal\u002Ferror",[221,325,249,326,329],{},[228,327,328],{},"AutoLinkByEmail"," off unless a verified provider email should attach to an existing confirmed account.",[221,331,332,333,336],{},"Keep ",[228,334,335],{},"RequireVerifiedEmail"," on.",[213,338,340],{"id":339},"check-the-browser-setup","Check the browser setup",[218,342,343,350],{},[221,344,345,346,349],{},"If the client runs on another origin, add a CORS policy with credentials. See ",[347,348,86],"a",{"href":87},".",[221,351,352,353,349],{},"Decide whether passkey and OAuth sign-in skipping 2FA fits your threat model. See ",[347,354,194],{"href":195},[213,356,358],{"id":357},"what-the-validators-check","What the validators check",[218,360,361,379,385,388],{},[221,362,363,366,367,370,371,374,375,378],{},[228,364,365],{},"AuthEndpointsOptionsValidator"," checks ",[228,368,369],{},"IdentityPath",", ",[228,372,373],{},"PasskeyPath",", and ",[228,376,377],{},"Jwt.Path"," formats, and the Production passkey domain.",[221,380,381,384],{},[228,382,383],{},"AuthEndpointsEmailSenderValidator"," checks the email sender in Production.",[221,386,387],{},"JWT options validation rejects the default issuer and audience in Production, and checks the key material against the signing algorithm.",[221,389,390,283,393,396,397,400,401,404],{},[228,391,392],{},"AddGitHub",[228,394,395],{},"AddGoogle"," reject an empty ",[228,398,399],{},"ClientId"," or ",[228,402,403],{},"ClientSecret"," at startup.",[213,406,408],{"id":407},"related","Related",[218,410,411,415,419,423],{},[221,412,413],{},[347,414,158],{"href":159},[221,416,417],{},[347,418,140],{"href":141},[221,420,421],{},[347,422,145],{"href":146},[221,424,425],{},[347,426,194],{"href":195},{"title":428,"searchDepth":429,"depth":430,"links":431},"",1,2,[432,433,434,435,436,437],{"id":215,"depth":430,"text":216},{"id":259,"depth":430,"text":260},{"id":300,"depth":430,"text":301},{"id":339,"depth":430,"text":340},{"id":357,"depth":430,"text":358},{"id":407,"depth":430,"text":408},"Checklist for running AuthEndpoints safely in Production.","md",null,{},{"icon":94},{"title":91,"description":438},"uu2Vo-ED_5K-TqOIp0p2ekmeqvjvGZ6d23KgXs9KWyA",[446,448],{"title":86,"path":87,"stem":88,"description":447,"icon":89,"children":-1},"Send cookies and CSRF tokens from a browser client, and set up CORS when the client runs on another origin.",{"title":102,"path":98,"stem":99,"description":449,"icon":103,"children":-1},"Compose Identity management, sign-in stacks, and passkeys on the prefixes your host needs.",1791096171186]