[{"data":1,"prerenderedAt":594},["ShallowReactive",2],{"navigation":3,"\u002Fmodules\u002Fcsrf":203,"\u002Fmodules\u002Fcsrf-surround":589},[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":163,"body":205,"description":582,"extension":583,"links":584,"meta":585,"navigation":586,"path":164,"seo":587,"stem":165,"__hash__":588},"docs\u002F4.modules\u002F10.csrf.md",{"type":206,"value":207,"toc":571},"minimark",[208,225,230,301,307,311,314,336,339,343,443,464,468,532,536,552,556],[209,210,211,212,216,217,220,221,224],"p",{},"AuthEndpoints adds the ",[213,214,215],"code",{},"EnforceAntiforgeryEndpointFilters"," endpoint filter through ",[213,218,219],{},"RequireAntiforgery()",". The filter validates the request with ASP.NET Core ",[213,222,223],{},"IAntiforgery",".",[226,227,229],"h2",{"id":228},"token","Token",[231,232,233,246],"table",{},[234,235,236],"thead",{},[237,238,239,243],"tr",{},[240,241,242],"th",{},"Item",[240,244,245],{},"Value",[247,248,249,265,276,287],"tbody",{},[237,250,251,255],{},[252,253,254],"td",{},"Token routes",[252,256,257,260,261,264],{},[213,258,259],{},"GET \u002Fidentity\u002FcsrfToken"," (cookie sign-in), ",[213,262,263],{},"GET \u002Fauth\u002FcsrfToken"," (JWT)",[237,266,267,270],{},[252,268,269],{},"Token response",[252,271,272,275],{},[213,273,274],{},"{ \"csrfToken\": \"...\" }"," plus the antiforgery cookie",[237,277,278,281],{},[252,279,280],{},"Request header",[252,282,283,286],{},[213,284,285],{},"RequestVerificationToken"," (the ASP.NET Core default)",[237,288,289,292],{},[252,290,291],{},"Failure",[252,293,294,297,298],{},[213,295,296],{},"400"," with the plain-text body ",[213,299,300],{},"Invalid or missing CSRF token.",[209,302,303,306],{},[213,304,305],{},"MapBearerAuthEndpoints"," maps no token route.",[226,308,310],{"id":309},"when-the-filter-skips-the-check","When the filter skips the check",[209,312,313],{},"The filter skips validation when both conditions are true:",[315,316,317,329],"ol",{},[318,319,320,321,324,325,328],"li",{},"The request is not authenticated by the ",[213,322,323],{},"Identity.Application"," or ",[213,326,327],{},"Identity.External"," cookie.",[318,330,331,332,335],{},"The request is authenticated by the ",[213,333,334],{},"Identity.Bearer"," scheme or the JWT bearer scheme.",[209,337,338],{},"An anonymous request is always checked. A request with an application cookie is always checked, even with a bearer token or a ReAuth cookie.",[226,340,342],{"id":341},"routes-that-require-a-token","Routes that require a token",[231,344,345,355],{},[234,346,347],{},[237,348,349,352],{},[240,350,351],{},"Module",[240,353,354],{},"Routes",[247,356,357,380,390,421,433],{},[237,358,359,362],{},[252,360,361],{},"Identity management",[252,363,364,367,368,367,371,367,374,367,377],{},[213,365,366],{},"POST \u002FresendConfirmationEmail",", ",[213,369,370],{},"POST \u002FconfirmIdentity",[213,372,373],{},"POST \u002FconfirmIdentity\u002FpasskeyOptions",[213,375,376],{},"POST \u002Fmanage\u002F2fa",[213,378,379],{},"POST \u002Fmanage\u002Finfo",[237,381,382,385],{},[252,383,384],{},"Cookie sign-in",[252,386,387],{},[213,388,389],{},"POST \u002Flogout",[237,391,392,395],{},[252,393,394],{},"Passkeys",[252,396,397,367,400,367,403,367,406,367,409,367,412,367,415,367,418],{},[213,398,399],{},"POST \u002Fpasskeys\u002FcreationOptions",[213,401,402],{},"POST \u002Fpasskeys\u002FrequestOptions",[213,404,405],{},"POST \u002Fpasskeys\u002Fregister\u002Foptions",[213,407,408],{},"POST \u002Fpasskeys\u002Fregister",[213,410,411],{},"POST \u002Fpasskeys\u002Flogin",[213,413,414],{},"POST \u002Fpasskeys\u002F",[213,416,417],{},"PATCH \u002Fpasskeys\u002F",[213,419,420],{},"DELETE \u002Fpasskeys\u002F{credentialIdUrl}",[237,422,423,426],{},[252,424,425],{},"JWT",[252,427,428,367,431],{},[213,429,430],{},"POST \u002Frefresh",[213,432,389],{},[237,434,435,438],{},[252,436,437],{},"External OAuth",[252,439,440],{},[213,441,442],{},"DELETE \u002Flogins\u002F{loginProvider}\u002F{providerKey}",[209,444,445,448,449,452,453,456,457,460,461,224],{},[213,446,447],{},"MapIdentityManagementApi"," maps the two ",[213,450,451],{},"confirmIdentity"," routes with ",[213,454,455],{},"requireAntiforgery: true",". ",[213,458,459],{},"MapReAuthEndpoints"," called on its own defaults to ",[213,462,463],{},"requireAntiforgery: false",[226,465,467],{"id":466},"routes-without-a-token-check","Routes without a token check",[469,470,471,491,497,506,512,521],"ul",{},[318,472,473,474,367,477,367,480,367,483,486,487,490],{},"Identity management: ",[213,475,476],{},"POST \u002Fregister",[213,478,479],{},"GET \u002FconfirmEmail",[213,481,482],{},"POST \u002FforgotPassword",[213,484,485],{},"POST \u002FresetPassword",", and the ",[213,488,489],{},"GET"," routes.",[318,492,493,494,224],{},"Cookie sign-in: ",[213,495,496],{},"POST \u002Flogin",[318,498,499,500,367,502,367,504,224],{},"Identity bearer sign-in: ",[213,501,496],{},[213,503,430],{},[213,505,389],{},[318,507,508,509,224],{},"Passkeys: ",[213,510,511],{},"GET \u002Fpasskeys\u002F",[318,513,514,515,367,518,224],{},"JWT: ",[213,516,517],{},"POST \u002Fcreate",[213,519,520],{},"GET \u002Fverify",[318,522,523,524,527,528,531],{},"External OAuth: the ",[213,525,526],{},"login"," and ",[213,529,530],{},"link"," routes and their callbacks. The OAuth correlation and state cookies protect the callbacks.",[226,533,535],{"id":534},"middleware","Middleware",[209,537,538,540,541,544,545,548,549,551],{},[213,539,219],{}," attaches only the endpoint filter. It does not add ASP.NET Core antiforgery metadata, so ",[213,542,543],{},"UseAntiforgery()"," does not reject the request before the filter's bearer check runs. ",[213,546,547],{},"AntiforgeryEnforcementMiddleware"," is optional. It rejects requests that ",[213,550,543],{}," already marked as invalid.",[226,553,555],{"id":554},"related","Related",[469,557,558,563,567],{},[318,559,560],{},[561,562,86],"a",{"href":87},[318,564,565],{},[561,566,121],{"href":122},[318,568,569],{},[561,570,194],{"href":195},{"title":572,"searchDepth":573,"depth":574,"links":575},"",1,2,[576,577,578,579,580,581],{"id":228,"depth":574,"text":229},{"id":309,"depth":574,"text":310},{"id":341,"depth":574,"text":342},{"id":466,"depth":574,"text":467},{"id":534,"depth":574,"text":535},{"id":554,"depth":574,"text":555},"Which AuthEndpoints routes require an antiforgery token, when the check is skipped, and what a failure returns.","md",null,{},{"icon":84},{"title":163,"description":582},"kGMragMYK4ITgKBOW1GVpkFl1MJuOcTQrdURV88BV44",[590,592],{"title":158,"path":159,"stem":160,"description":591,"icon":161,"children":-1},"Reference for AuthEndpointsOptions and nested passkey, JWT, ReAuth, and email confirmation settings.",{"title":167,"path":168,"stem":169,"description":593,"icon":170,"children":-1},"Success and error response shapes for every AuthEndpoints module.",1791096172876]