[{"data":1,"prerenderedAt":1828},["ShallowReactive",2],{"navigation":3,"\u002Fconcepts\u002Fmapidentityapi-alternative":250,"\u002Fconcepts\u002Fmapidentityapi-alternative-surround":1823},[4,43,120,143,219],{"title":5,"path":6,"stem":7,"children":8,"icon":42},"Get started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12,17,22,27,32,37],{"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},"Pick your setup","\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",{"title":33,"path":34,"stem":35,"icon":36},"Password auth","\u002Fgetting-started\u002Fpassword-auth","1.getting-started\u002F6.password-auth","i-lucide-key-round",{"title":38,"path":39,"stem":40,"icon":41},"3.x facade","\u002Fgetting-started\u002Fcompatibility-facade","1.getting-started\u002F7.compatibility-facade","i-lucide-archive","i-lucide-rocket",{"title":44,"path":45,"stem":46,"children":47,"icon":119},"Guides","\u002Fguides","2.guides\u002F01.index",[48,50,55,60,65,70,74,79,84,89,94,99,104,109,114],{"title":44,"path":45,"stem":46,"icon":49},"i-lucide-list-checks",{"title":51,"path":52,"stem":53,"icon":54},"Register users","\u002Fguides\u002Fregistration","2.guides\u002F02.registration","i-lucide-user-plus",{"title":56,"path":57,"stem":58,"icon":59},"Sign users in","\u002Fguides\u002Fsign-in","2.guides\u002F03.sign-in","i-lucide-log-in",{"title":61,"path":62,"stem":63,"icon":64},"Sign users out","\u002Fguides\u002Fsign-out","2.guides\u002F04.sign-out","i-lucide-log-out",{"title":66,"path":67,"stem":68,"icon":69},"Turn on two-factor authentication","\u002Fguides\u002Ftwo-factor","2.guides\u002F05.two-factor","i-lucide-smartphone",{"title":71,"path":72,"stem":73,"icon":36},"Reset a forgotten password","\u002Fguides\u002Freset-password","2.guides\u002F06.reset-password",{"title":75,"path":76,"stem":77,"icon":78},"Change a user's email or password","\u002Fguides\u002Fmanage-account","2.guides\u002F07.manage-account","i-lucide-user-cog",{"title":80,"path":81,"stem":82,"icon":83},"Add, rename, and remove passkeys","\u002Fguides\u002Fmanage-passkeys","2.guides\u002F08.manage-passkeys","i-lucide-scan-face",{"title":85,"path":86,"stem":87,"icon":88},"Link and unlink GitHub or Google accounts","\u002Fguides\u002Flink-external-accounts","2.guides\u002F09.link-external-accounts","i-lucide-link",{"title":90,"path":91,"stem":92,"icon":93},"Require step-up before sensitive actions","\u002Fguides\u002Fstep-up","2.guides\u002F10.step-up","i-lucide-shield-check",{"title":95,"path":96,"stem":97,"icon":98},"Call the API from a browser","\u002Fguides\u002Fbrowser-clients","2.guides\u002F11.browser-clients","i-lucide-globe",{"title":100,"path":101,"stem":102,"icon":103},"Prepare for production","\u002Fguides\u002Fproduction","2.guides\u002F12.production","i-lucide-factory",{"title":105,"path":106,"stem":107,"icon":108},"Sign in with an emailed code","\u002Fguides\u002Femail-code","2.guides\u002F13.email-code","i-lucide-mail",{"title":110,"path":111,"stem":112,"icon":113},"Upgrade to 4.0","\u002Fguides\u002Fupgrading-to-4","2.guides\u002F14.upgrading-to-4","i-lucide-arrow-up-right",{"title":115,"path":116,"stem":117,"icon":118},"Run an app with no public sign-up","\u002Fguides\u002Finternal-app","2.guides\u002F15.internal-app","i-lucide-building-2","i-lucide-waypoints",{"title":121,"path":122,"stem":123,"children":124,"icon":142},"Composable endpoints","\u002Fcomposables","3.composables\u002F1.index",[125,128,132,137],{"title":126,"path":122,"stem":123,"icon":127},"How composition works","i-lucide-layout-grid",{"title":129,"path":130,"stem":131,"icon":49},"Composition requirements","\u002Fcomposables\u002Frequirements","3.composables\u002F2.requirements",{"title":133,"path":134,"stem":135,"icon":136},"Compose a custom auth stack","\u002Fcomposables\u002Frecipes","3.composables\u002F3.recipes","i-lucide-book-marked",{"title":138,"path":139,"stem":140,"icon":141},"Composition","\u002Fcomposables\u002Fcomposition","3.composables\u002F4.composition","i-lucide-table","i-lucide-blocks",{"title":144,"icon":145,"path":146,"stem":147,"children":148,"page":218},"Reference","i-lucide-book-open","\u002Fmodules","4.modules",[149,154,158,163,168,173,177,182,186,191,195,200,205,209,213],{"title":150,"path":151,"stem":152,"icon":153},"Endpoint reference","\u002Fmodules\u002Fendpoints","4.modules\u002F01.endpoints","i-lucide-route",{"title":155,"path":156,"stem":157,"icon":78},"Identity management module","\u002Fmodules\u002Fidentity-management","4.modules\u002F02.identity-management",{"title":159,"path":160,"stem":161,"icon":162},"Cookie sign-in module","\u002Fmodules\u002Fcookie-auth","4.modules\u002F03.cookie-auth","i-lucide-cookie",{"title":164,"path":165,"stem":166,"icon":167},"Identity bearer sign-in module","\u002Fmodules\u002Fbearer-auth","4.modules\u002F04.bearer-auth","i-lucide-key",{"title":169,"path":170,"stem":171,"icon":172},"JWT module","\u002Fmodules\u002Fjwt","4.modules\u002F05.jwt","i-lucide-fingerprint",{"title":174,"path":175,"stem":176,"icon":83},"Passkeys module","\u002Fmodules\u002Fpasskeys","4.modules\u002F06.passkeys",{"title":178,"path":179,"stem":180,"icon":181},"ReAuth module","\u002Fmodules\u002Freauth","4.modules\u002F07.reauth","i-lucide-shield-alert",{"title":183,"path":184,"stem":185,"icon":59},"External OAuth packages","\u002Fmodules\u002Fexternal-oauth","4.modules\u002F08.external-oauth",{"title":187,"path":188,"stem":189,"icon":190},"Configuration options","\u002Fmodules\u002Fconfiguration","4.modules\u002F09.configuration","i-lucide-settings",{"title":192,"path":193,"stem":194,"icon":93},"Antiforgery (CSRF) rules","\u002Fmodules\u002Fcsrf","4.modules\u002F10.csrf",{"title":196,"path":197,"stem":198,"icon":199},"Responses and errors","\u002Fmodules\u002Ferrors","4.modules\u002F11.errors","i-lucide-circle-alert",{"title":201,"path":202,"stem":203,"icon":204},"Rate-limit policies","\u002Fmodules\u002Frate-limits","4.modules\u002F12.rate-limits","i-lucide-gauge",{"title":206,"path":207,"stem":208,"icon":108},"Email-code module","\u002Fmodules\u002Femail-code","4.modules\u002F13.email-code",{"title":210,"path":211,"stem":212,"icon":59},"Sign-in completer","\u002Fmodules\u002Fsign-in-completer","4.modules\u002F14.sign-in-completer",{"title":214,"path":215,"stem":216,"icon":217},"Enumeration-safe responses","\u002Fmodules\u002Fenumeration","4.modules\u002F15.enumeration","i-lucide-eye-off",false,{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":218},"Concepts","i-lucide-lightbulb","\u002Fconcepts","5.concepts",[225,230,235,240,245],{"title":226,"path":227,"stem":228,"icon":229},"AuthEndpoints compared with other options","\u002Fconcepts\u002Fcompare","5.concepts\u002F1.compare","i-lucide-git-compare",{"title":231,"path":232,"stem":233,"icon":234},"Stock Identity endpoints vs AuthEndpoints","\u002Fconcepts\u002Fstock-identity-vs-authendpoints","5.concepts\u002F2.stock-identity-vs-authendpoints","i-lucide-columns-2",{"title":236,"path":237,"stem":238,"icon":239},"MapIdentityApi alternative","\u002Fconcepts\u002Fmapidentityapi-alternative","5.concepts\u002F3.mapidentityapi-alternative","i-lucide-arrow-left-right",{"title":241,"path":242,"stem":243,"icon":244},"Security model","\u002Fconcepts\u002Fsecurity-model","5.concepts\u002F4.security-model","i-lucide-shield",{"title":246,"path":247,"stem":248,"icon":249},"FAQ","\u002Fconcepts\u002Ffaq","5.concepts\u002F5.faq","i-lucide-circle-help",{"id":251,"title":236,"body":252,"description":1816,"extension":1817,"faq":218,"links":1818,"meta":1819,"navigation":1820,"path":237,"seo":1821,"stem":238,"__hash__":1822},"docs\u002F5.concepts\u002F3.mapidentityapi-alternative.md",{"type":253,"value":254,"toc":1807},"minimark",[255,267,275,280,289,420,520,546,550,570,576,631,634,672,681,685,702,705,906,931,938,1115,1155,1166,1224,1234,1238,1282,1288,1353,1378,1384,1579,1603,1606,1625,1653,1714,1750,1754,1760,1764,1803],[256,257,258,262,263,266],"p",{},[259,260,261],"code",{},"MapIdentityApi\u003CTUser>()"," is ASP.NET Core's Identity API. One call maps register, login, refresh, email confirmation, password reset, and account management onto your Identity user store. AuthEndpoints uses that same store. This page lists where ",[259,264,265],{},"MapIdentityApi"," stops in .NET 10, and which AuthEndpoints call covers each gap.",[256,268,269,270,274],{},"Register, login, password reset, and two-factor authentication, route by route: ",[271,272,231],"a",{"href":273},"\u002Fconcepts\u002Fstock-identity-vs-authendpoints\u002F",".",[276,277,279],"h2",{"id":278},"what-mapidentityapi-maps","What MapIdentityApi maps",[256,281,282,283,285,286,274],{},"In .NET 10, ",[259,284,261],{}," maps this set. Paths sit at the app root unless you wrap the call in ",[259,287,288],{},"MapGroup",[290,291,292,305],"table",{},[293,294,295],"thead",{},[296,297,298,302],"tr",{},[299,300,301],"th",{},"Method",[299,303,304],{},"Path",[306,307,308,321,332,343,355,366,377,388,399,410],"tbody",{},[296,309,310,316],{},[311,312,313],"td",{},[259,314,315],{},"POST",[311,317,318],{},[259,319,320],{},"\u002Fregister",[296,322,323,327],{},[311,324,325],{},[259,326,315],{},[311,328,329],{},[259,330,331],{},"\u002Flogin",[296,333,334,338],{},[311,335,336],{},[259,337,315],{},[311,339,340],{},[259,341,342],{},"\u002Frefresh",[296,344,345,350],{},[311,346,347],{},[259,348,349],{},"GET",[311,351,352],{},[259,353,354],{},"\u002FconfirmEmail",[296,356,357,361],{},[311,358,359],{},[259,360,315],{},[311,362,363],{},[259,364,365],{},"\u002FresendConfirmationEmail",[296,367,368,372],{},[311,369,370],{},[259,371,315],{},[311,373,374],{},[259,375,376],{},"\u002FforgotPassword",[296,378,379,383],{},[311,380,381],{},[259,382,315],{},[311,384,385],{},[259,386,387],{},"\u002FresetPassword",[296,389,390,394],{},[311,391,392],{},[259,393,315],{},[311,395,396],{},[259,397,398],{},"\u002Fmanage\u002F2fa",[296,400,401,405],{},[311,402,403],{},[259,404,349],{},[311,406,407],{},[259,408,409],{},"\u002Fmanage\u002Finfo",[296,411,412,416],{},[311,413,414],{},[259,415,315],{},[311,417,418],{},[259,419,409],{},[421,422,427],"pre",{"className":423,"code":424,"language":425,"meta":426,"style":426},"language-cs shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","builder.Services\n    .AddIdentityApiEndpoints\u003CAppUser>()\n    .AddEntityFrameworkStores\u003CAppDbContext>();\n\napp.MapGroup(\"\u002Fidentity\").MapIdentityApi\u003CAppUser>();\n","cs","",[259,428,429,444,464,480,487],{"__ignoreMap":426},[430,431,434,438,441],"span",{"class":432,"line":433},"line",1,[430,435,437],{"class":436},"sTEyZ","builder",[430,439,274],{"class":440},"sMK4o",[430,442,443],{"class":436},"Services\n",[430,445,447,450,454,457,461],{"class":432,"line":446},2,[430,448,449],{"class":440},"    .",[430,451,453],{"class":452},"s2Zo4","AddIdentityApiEndpoints",[430,455,456],{"class":440},"\u003C",[430,458,460],{"class":459},"sBMFI","AppUser",[430,462,463],{"class":440},">()\n",[430,465,467,469,472,474,477],{"class":432,"line":466},3,[430,468,449],{"class":440},[430,470,471],{"class":452},"AddEntityFrameworkStores",[430,473,456],{"class":440},[430,475,476],{"class":459},"AppDbContext",[430,478,479],{"class":440},">();\n",[430,481,483],{"class":432,"line":482},4,[430,484,486],{"emptyLinePlaceholder":485},true,"\n",[430,488,490,493,495,497,500,503,507,509,512,514,516,518],{"class":432,"line":489},5,[430,491,492],{"class":436},"app",[430,494,274],{"class":440},[430,496,288],{"class":452},[430,498,499],{"class":440},"(",[430,501,502],{"class":440},"\"",[430,504,506],{"class":505},"sfazB","\u002Fidentity",[430,508,502],{"class":440},[430,510,511],{"class":440},").",[430,513,265],{"class":452},[430,515,456],{"class":440},[430,517,460],{"class":459},[430,519,479],{"class":440},[256,521,522,525,526,529,530,533,534,537,538,541,542,545],{},[259,523,524],{},"POST \u002Flogin"," uses the Identity bearer scheme unless the query string sets ",[259,527,528],{},"useCookies"," or ",[259,531,532],{},"useSessionCookies",", which issue the application cookie instead. Request bodies are the Identity types (",[259,535,536],{},"RegisterRequest",", ",[259,539,540],{},"LoginRequest",", and the rest). There is no ",[259,543,544],{},"GET \u002Fmanage\u002F2fa",". The method's documentation comment mentions logging out. The method does not map a logout route.",[276,547,549],{"id":548},"logout","Logout",[256,551,552,554,555,561,562,565,566,569],{},[259,553,265],{}," has no logout route. The ",[271,556,560],{"href":557,"rel":558},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Faspnet\u002Fcore\u002Fsecurity\u002Fauthentication\u002Fidentity-api-authorization?view=aspnetcore-10.0",[559],"nofollow","Identity API authorization"," article tells you to add your own ",[259,563,564],{},"POST \u002Flogout"," that calls ",[259,567,568],{},"SignInManager.SignOutAsync()",". That signs out the application scheme, plus the external and two-factor user-id schemes when they are registered. It does not sign out the two-factor remember-client cookie. It does not revoke bearer tokens. The bearer handler treats sign-out as a no-op, so the access token and the refresh token stay valid until they expire.",[256,571,572,573,274],{},"AuthEndpoints maps a logout route on each sign-in stack. Each stack ends a different thing. Client steps: ",[271,574,61],{"href":575},"\u002Fguides\u002Fsign-out\u002F",[290,577,578,591],{},[293,579,580],{},[296,581,582,585,588],{},[299,583,584],{},"Stack",[299,586,587],{},"Route",[299,589,590],{},"What logout ends",[306,592,593,606,618],{},[296,594,595,598,603],{},[311,596,597],{},"Cookie (facade default)",[311,599,600],{},[259,601,602],{},"POST \u002Fidentity\u002Flogout",[311,604,605],{},"Application, external, two-factor user-id, remember-client, and ReAuth cookies. Requires a signed-in user and a CSRF token.",[296,607,608,611,615],{},[311,609,610],{},"Identity bearer",[311,612,613],{},[259,614,602],{},[311,616,617],{},"Those same cookies. Bearer access and refresh tokens stay valid until they expire. Requires a signed-in user. No CSRF token.",[296,619,620,623,628],{},[311,621,622],{},"JWT",[311,624,625],{},[259,626,627],{},"POST \u002Fauth\u002Flogout",[311,629,630],{},"The refresh-token family for the refresh cookie, and the cookie itself. The access JWT stays valid until it expires (15 minutes by default). CSRF token required. A signed-in user is not required.",[256,632,633],{},"Cookie logout:",[421,635,639],{"className":636,"code":637,"language":638,"meta":426,"style":426},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const { csrfToken } = await fetch('\u002Fidentity\u002FcsrfToken', { credentials: 'include' }).then(r => r.json());\nawait fetch('\u002Fidentity\u002Flogout', {\n  method: 'POST',\n  credentials: 'include',\n  headers: { 'RequestVerificationToken': csrfToken }\n});\n","js",[259,640,641,646,651,656,661,666],{"__ignoreMap":426},[430,642,643],{"class":432,"line":433},[430,644,645],{},"const { csrfToken } = await fetch('\u002Fidentity\u002FcsrfToken', { credentials: 'include' }).then(r => r.json());\n",[430,647,648],{"class":432,"line":446},[430,649,650],{},"await fetch('\u002Fidentity\u002Flogout', {\n",[430,652,653],{"class":432,"line":466},[430,654,655],{},"  method: 'POST',\n",[430,657,658],{"class":432,"line":482},[430,659,660],{},"  credentials: 'include',\n",[430,662,663],{"class":432,"line":489},[430,664,665],{},"  headers: { 'RequestVerificationToken': csrfToken }\n",[430,667,669],{"class":432,"line":668},6,[430,670,671],{},"});\n",[256,673,674,677,678,680],{},[259,675,676],{},"GET \u002Fidentity\u002FcsrfToken"," is part of the cookie module. ",[259,679,265],{}," does not map it.",[276,682,684],{"id":683},"choose-which-endpoints-to-map","Choose which endpoints to map",[256,686,687,689,690,693,694,696,697,699,700,274],{},[259,688,265],{}," maps the full table above in one call. ",[259,691,692],{},"MapGroup(\"\u002Fidentity\")"," prefixes every route with ",[259,695,506],{},". The builder it returns can add conventions to that group. It has no parameter that omits ",[259,698,320],{},", and no parameter that renames ",[259,701,331],{},[256,703,704],{},"AuthEndpoints splits the same jobs into modules. Map the ones you need:",[290,706,707,717],{},[293,708,709],{},[296,710,711,714],{},[299,712,713],{},"Module",[299,715,716],{},"What it adds",[306,718,719,729,743,760,773,790,803,820,833,855,866,876,886,896],{},[296,720,721,726],{},[311,722,723],{},[259,724,725],{},"MapIdentityManagementApi",[311,727,728],{},"Register, confirm email, resend, forgot\u002Freset password, manage info, set password, 2FA, ReAuth",[296,730,731,736],{},[311,732,733],{},[259,734,735],{},"MapPasswordEndpoints",[311,737,738,739,742],{},"Register, forgot\u002Freset password, and login for cookie or Identity bearer. ",[259,740,741],{},"PasswordLoginMode.None"," omits login.",[296,744,745,750],{},[311,746,747],{},[259,748,749],{},"MapConfirmEmailEndpoints",[311,751,752,755,756,759],{},[259,753,754],{},"GET \u002FconfirmEmail"," and ",[259,757,758],{},"POST \u002FresendConfirmationEmail",", once per endpoint name",[296,761,762,767],{},[311,763,764],{},[259,765,766],{},"MapAccountManagementEndpoints",[311,768,769,770],{},"Manage info, set password, 2FA, auth methods, and ",[259,771,772],{},"POST \u002FconfirmIdentity",[296,774,775,780],{},[311,776,777],{},[259,778,779],{},"MapCookieAuthEndpoints",[311,781,782,783,537,785,537,787],{},"Cookie ",[259,784,524],{},[259,786,564],{},[259,788,789],{},"GET \u002FcsrfToken",[296,791,792,797],{},[311,793,794],{},[259,795,796],{},"MapCookieSessionEndpoints",[311,798,782,799,755,801],{},[259,800,564],{},[259,802,789],{},[296,804,805,810],{},[311,806,807],{},[259,808,809],{},"MapBearerAuthEndpoints",[311,811,812,813,537,815,537,818],{},"Identity bearer ",[259,814,524],{},[259,816,817],{},"POST \u002Frefresh",[259,819,564],{},[296,821,822,827],{},[311,823,824],{},[259,825,826],{},"MapBearerSessionEndpoints",[311,828,812,829,755,831],{},[259,830,817],{},[259,832,564],{},[296,834,835,840],{},[311,836,837],{},[259,838,839],{},"MapJwtAuthEndpoints",[311,841,842,843,537,846,537,848,537,851,537,853],{},"JWT ",[259,844,845],{},"POST \u002Fcreate",[259,847,817],{},[259,849,850],{},"GET \u002Fverify",[259,852,564],{},[259,854,789],{},[296,856,857,862],{},[311,858,859],{},[259,860,861],{},"MapJwtPasswordEndpoints",[311,863,842,864],{},[259,865,845],{},[296,867,868,873],{},[311,869,870],{},[259,871,872],{},"MapJwtSessionEndpoints",[311,874,875],{},"JWT refresh, verify, logout, and CSRF token",[296,877,878,883],{},[311,879,880],{},[259,881,882],{},"MapPasskeyEndpoints",[311,884,885],{},"Passkey register, login, and credential management",[296,887,888,893],{},[311,889,890],{},[259,891,892],{},"MapPasskeySignInEndpoints",[311,894,895],{},"Passkey register and login, plus confirm-email on the parent group when that name is new",[296,897,898,903],{},[311,899,900],{},[259,901,902],{},"MapPasskeyManagementEndpoints",[311,904,905],{},"Signed-in passkey list, add, rename, and delete",[256,907,908,909,912,913,916,917,919,920,916,923,926,927,930],{},"The 3.x facade (",[259,910,911],{},"MapAuthEndpoints",") is one composition: management plus either cookie or Identity bearer sign-in under ",[259,914,915],{},"IdentityPath"," (default ",[259,918,506],{},"). Passkeys are on by default under ",[259,921,922],{},"PasskeyPath",[259,924,925],{},"\u002Faccount","). JWT is off until ",[259,928,929],{},"Jwt.Enabled"," is true.",[256,932,933,934,937],{},"This maps management and cookie sign-in under ",[259,935,936],{},"\u002Fapi\u002Faccount",", with passkeys and JWT left off:",[421,939,941],{"className":423,"code":940,"language":425,"meta":426,"style":426},"builder.Services.AddAuthEndpoints\u003CAppUser, AppDbContext>(o =>\n{\n    o.IdentityPath = \"\u002Fapi\u002Faccount\";\n    o.Passkeys.Enabled = false;\n});\nbuilder.Services.AddTransient\u003CIEmailSender\u003CAppUser>, MyEmailSender>();\n\nvar app = builder.Build();\napp.UseAuthEndpoints();\napp.MapAuthEndpoints\u003CAppUser>();\n",[259,942,943,976,981,1004,1026,1030,1060,1065,1088,1100],{"__ignoreMap":426},[430,944,945,947,949,952,954,957,959,961,964,967,970,973],{"class":432,"line":433},[430,946,437],{"class":436},[430,948,274],{"class":440},[430,950,951],{"class":436},"Services",[430,953,274],{"class":440},[430,955,956],{"class":452},"AddAuthEndpoints",[430,958,456],{"class":440},[430,960,460],{"class":459},[430,962,963],{"class":440},",",[430,965,966],{"class":459}," AppDbContext",[430,968,969],{"class":440},">(",[430,971,972],{"class":459},"o",[430,974,975],{"class":440}," =>\n",[430,977,978],{"class":432,"line":446},[430,979,980],{"class":440},"{\n",[430,982,983,986,988,991,994,997,999,1001],{"class":432,"line":466},[430,984,985],{"class":436},"    o",[430,987,274],{"class":440},[430,989,990],{"class":436},"IdentityPath ",[430,992,993],{"class":440},"=",[430,995,996],{"class":440}," \"",[430,998,936],{"class":505},[430,1000,502],{"class":440},[430,1002,1003],{"class":440},";\n",[430,1005,1006,1008,1010,1013,1015,1018,1020,1024],{"class":432,"line":482},[430,1007,985],{"class":436},[430,1009,274],{"class":440},[430,1011,1012],{"class":436},"Passkeys",[430,1014,274],{"class":440},[430,1016,1017],{"class":436},"Enabled ",[430,1019,993],{"class":440},[430,1021,1023],{"class":1022},"sfNiH"," false",[430,1025,1003],{"class":440},[430,1027,1028],{"class":432,"line":489},[430,1029,671],{"class":440},[430,1031,1032,1034,1036,1038,1040,1043,1045,1048,1050,1052,1055,1058],{"class":432,"line":668},[430,1033,437],{"class":436},[430,1035,274],{"class":440},[430,1037,951],{"class":436},[430,1039,274],{"class":440},[430,1041,1042],{"class":452},"AddTransient",[430,1044,456],{"class":440},[430,1046,1047],{"class":459},"IEmailSender",[430,1049,456],{"class":440},[430,1051,460],{"class":459},[430,1053,1054],{"class":440},">,",[430,1056,1057],{"class":459}," MyEmailSender",[430,1059,479],{"class":440},[430,1061,1063],{"class":432,"line":1062},7,[430,1064,486],{"emptyLinePlaceholder":485},[430,1066,1068,1071,1074,1077,1080,1082,1085],{"class":432,"line":1067},8,[430,1069,1070],{"class":459},"var",[430,1072,1073],{"class":459}," app",[430,1075,1076],{"class":440}," =",[430,1078,1079],{"class":436}," builder",[430,1081,274],{"class":440},[430,1083,1084],{"class":452},"Build",[430,1086,1087],{"class":440},"();\n",[430,1089,1091,1093,1095,1098],{"class":432,"line":1090},9,[430,1092,492],{"class":436},[430,1094,274],{"class":440},[430,1096,1097],{"class":452},"UseAuthEndpoints",[430,1099,1087],{"class":440},[430,1101,1103,1105,1107,1109,1111,1113],{"class":432,"line":1102},10,[430,1104,492],{"class":436},[430,1106,274],{"class":440},[430,1108,911],{"class":452},[430,1110,456],{"class":440},[430,1112,460],{"class":459},[430,1114,479],{"class":440},[256,1116,1117,1120,1121,537,1123,1125,1126,1129,1130,1132,1133,1135,1136,1132,1138,1140,1141,1143,1144,1146,1147,1125,1149,1151,1152,274],{},[259,1118,1119],{},"POST \u002Fapi\u002Faccount\u002Flogin"," on that host is cookie login. The relative names stay ",[259,1122,331],{},[259,1124,320],{},", and ",[259,1127,1128],{},"\u002Flogout",". AuthEndpoints does not rename those segments. ",[259,1131,725],{}," always includes ",[259,1134,320],{},". ",[259,1137,779],{},[259,1139,331],{},". The smaller maps omit a piece: ",[259,1142,735],{}," with ",[259,1145,741],{}," skips ",[259,1148,331],{},[259,1150,796],{}," maps logout and the CSRF token. An email-code host uses those pieces. See ",[271,1153,133],{"href":1154},"\u002Fcomposables\u002Frecipes\u002F#email-code-only",[256,1156,1157,1158,1161,1162,1165],{},"To skip cookie login and map JWT instead, compose the modules. Register the matching services first, call ",[259,1159,1160],{},"modelBuilder.UseRefreshToken()"," on the ",[259,1163,1164],{},"DbContext",", and migrate. The route map is:",[421,1167,1169],{"className":423,"code":1168,"language":425,"meta":426,"style":426},"app.MapGroup(\"\u002Faccount\").MapIdentityManagementApi\u003CAppUser>();\napp.MapGroup(\"\u002Fauth\").MapJwtAuthEndpoints\u003CAppUser>();\n",[259,1170,1171,1197],{"__ignoreMap":426},[430,1172,1173,1175,1177,1179,1181,1183,1185,1187,1189,1191,1193,1195],{"class":432,"line":433},[430,1174,492],{"class":436},[430,1176,274],{"class":440},[430,1178,288],{"class":452},[430,1180,499],{"class":440},[430,1182,502],{"class":440},[430,1184,925],{"class":505},[430,1186,502],{"class":440},[430,1188,511],{"class":440},[430,1190,725],{"class":452},[430,1192,456],{"class":440},[430,1194,460],{"class":459},[430,1196,479],{"class":440},[430,1198,1199,1201,1203,1205,1207,1209,1212,1214,1216,1218,1220,1222],{"class":432,"line":446},[430,1200,492],{"class":436},[430,1202,274],{"class":440},[430,1204,288],{"class":452},[430,1206,499],{"class":440},[430,1208,502],{"class":440},[430,1210,1211],{"class":505},"\u002Fauth",[430,1213,502],{"class":440},[430,1215,511],{"class":440},[430,1217,839],{"class":452},[430,1219,456],{"class":440},[430,1221,460],{"class":459},[430,1223,479],{"class":440},[256,1225,1226,1227,1230,1231,274],{},"Full host setup: ",[271,1228,133],{"href":1229},"\u002Fcomposables\u002Frecipes\u002F",". Prefix reference: ",[271,1232,187],{"href":1233},"\u002Fmodules\u002Fconfiguration\u002F",[276,1235,1237],{"id":1236},"jwt-opaque-bearer-tokens-and-cookies","JWT, opaque bearer tokens, and cookies",[256,1239,1240,1242,1243,529,1245,1247,1248,537,1251,537,1254,537,1257,1260,1261,755,1264,1267,1268,1271,1272,529,1275,1278,1279,1281],{},[259,1241,265],{}," login without ",[259,1244,528],{},[259,1246,532],{}," returns Identity bearer tokens (",[259,1249,1250],{},"accessToken",[259,1252,1253],{},"refreshToken",[259,1255,1256],{},"expiresIn",[259,1258,1259],{},"tokenType","). Those values are data-protection tickets (",[259,1262,1263],{},"BearerTokenProtector",[259,1265,1266],{},"RefreshTokenProtector","), not JWTs. Microsoft's Identity API article states that the tokens are not standard JSON Web Tokens. Another service validates them with the Identity bearer handler and the same data-protection keys. ",[259,1269,1270],{},"JwtBearer"," and a signing key do not validate them. ",[259,1273,1274],{},"?useCookies=true",[259,1276,1277],{},"?useSessionCookies=true"," on that same ",[259,1280,331],{}," issues the application cookie and does not return a token body.",[256,1283,1284,1285,1287],{},"AuthEndpoints has three password sign-in stacks. Identity bearer is the same ticket format as ",[259,1286,265],{},". JWT is a separate opt-in.",[290,1289,1290,1302],{},[293,1291,1292],{},[296,1293,1294,1296,1299],{},[299,1295,584],{},[299,1297,1298],{},"What login returns",[299,1300,1301],{},"Refresh",[306,1303,1304,1314,1334],{},[296,1305,1306,1308,1311],{},[311,1307,597],{},[311,1309,1310],{},"Application cookie. Empty body.",[311,1312,1313],{},"The browser sends the cookie.",[296,1315,1316,1318,1326],{},[311,1317,610],{},[311,1319,1320,1321,755,1323,1325],{},"Opaque ",[259,1322,1250],{},[259,1324,1253],{}," in the body",[311,1327,1328,1143,1331],{},[259,1329,1330],{},"POST \u002Fidentity\u002Frefresh",[259,1332,1333],{},"{ \"refreshToken\" }",[296,1335,1336,1338,1347],{},[311,1337,622],{},[311,1339,842,1340,1342,1343,1346],{},[259,1341,1250],{}," in the body, refresh token in the ",[259,1344,1345],{},"AuthEndpoints.Jwt.RefreshToken"," cookie",[311,1348,1349,1352],{},[259,1350,1351],{},"POST \u002Fauth\u002Frefresh"," with that cookie and a CSRF token. The stored token is a hash. Each refresh rotates it. Reuse of an old token revokes the family.",[256,1354,1355,1356,1359,1360,1362,1363,1366,1367,1369,1370,1372,1373,755,1376,274],{},"On the 3.x cookie facade, ",[259,1357,1358],{},"POST \u002Fidentity\u002Flogin"," always uses the application cookie. ",[259,1361,528],{}," is ignored there. A persistent cookie is ",[259,1364,1365],{},"?useSessionCookies=false",". The flag table for Identity bearer login matches ",[259,1368,265],{},". The password facade uses ",[259,1371,1211],{}," and the same cookie rule. Details: ",[271,1374,23],{"href":1375},"\u002Fgetting-started\u002Fchoose-a-sign-in-stack\u002F",[271,1377,231],{"href":273},[256,1379,1380,1381,1383],{},"Turn JWT on beside the cookie facade. You still call ",[259,1382,1160],{}," and add a migration:",[421,1385,1387],{"className":423,"code":1386,"language":425,"meta":426,"style":426},"builder.Services.AddAuthEndpoints\u003CAppUser, AppDbContext>(o =>\n{\n    o.Passkeys.ServerDomain = \"example.com\"; \u002F\u002F required in Production while passkeys stay on\n    o.Jwt.Enabled = true;\n    o.Jwt.Configure = jwt =>\n    {\n        jwt.Issuer = \"https:\u002F\u002Fexample.com\";\n        jwt.Audience = \"https:\u002F\u002Fexample.com\";\n        jwt.SigningOptions.SymmetricKey = builder.Configuration[\"Jwt:SymmetricKey\"];\n    };\n});\n",[259,1388,1389,1415,1419,1448,1468,1488,1493,1514,1533,1569,1574],{"__ignoreMap":426},[430,1390,1391,1393,1395,1397,1399,1401,1403,1405,1407,1409,1411,1413],{"class":432,"line":433},[430,1392,437],{"class":436},[430,1394,274],{"class":440},[430,1396,951],{"class":436},[430,1398,274],{"class":440},[430,1400,956],{"class":452},[430,1402,456],{"class":440},[430,1404,460],{"class":459},[430,1406,963],{"class":440},[430,1408,966],{"class":459},[430,1410,969],{"class":440},[430,1412,972],{"class":459},[430,1414,975],{"class":440},[430,1416,1417],{"class":432,"line":446},[430,1418,980],{"class":440},[430,1420,1421,1423,1425,1427,1429,1432,1434,1436,1439,1441,1444],{"class":432,"line":466},[430,1422,985],{"class":436},[430,1424,274],{"class":440},[430,1426,1012],{"class":436},[430,1428,274],{"class":440},[430,1430,1431],{"class":436},"ServerDomain ",[430,1433,993],{"class":440},[430,1435,996],{"class":440},[430,1437,1438],{"class":505},"example.com",[430,1440,502],{"class":440},[430,1442,1443],{"class":440},";",[430,1445,1447],{"class":1446},"sHwdD"," \u002F\u002F required in Production while passkeys stay on\n",[430,1449,1450,1452,1454,1457,1459,1461,1463,1466],{"class":432,"line":482},[430,1451,985],{"class":436},[430,1453,274],{"class":440},[430,1455,1456],{"class":436},"Jwt",[430,1458,274],{"class":440},[430,1460,1017],{"class":436},[430,1462,993],{"class":440},[430,1464,1465],{"class":1022}," true",[430,1467,1003],{"class":440},[430,1469,1470,1472,1474,1476,1478,1481,1483,1486],{"class":432,"line":489},[430,1471,985],{"class":436},[430,1473,274],{"class":440},[430,1475,1456],{"class":436},[430,1477,274],{"class":440},[430,1479,1480],{"class":436},"Configure ",[430,1482,993],{"class":440},[430,1484,1485],{"class":459}," jwt",[430,1487,975],{"class":440},[430,1489,1490],{"class":432,"line":668},[430,1491,1492],{"class":440},"    {\n",[430,1494,1495,1498,1500,1503,1505,1507,1510,1512],{"class":432,"line":1062},[430,1496,1497],{"class":436},"        jwt",[430,1499,274],{"class":440},[430,1501,1502],{"class":436},"Issuer ",[430,1504,993],{"class":440},[430,1506,996],{"class":440},[430,1508,1509],{"class":505},"https:\u002F\u002Fexample.com",[430,1511,502],{"class":440},[430,1513,1003],{"class":440},[430,1515,1516,1518,1520,1523,1525,1527,1529,1531],{"class":432,"line":1067},[430,1517,1497],{"class":436},[430,1519,274],{"class":440},[430,1521,1522],{"class":436},"Audience ",[430,1524,993],{"class":440},[430,1526,996],{"class":440},[430,1528,1509],{"class":505},[430,1530,502],{"class":440},[430,1532,1003],{"class":440},[430,1534,1535,1537,1539,1542,1544,1547,1549,1551,1553,1556,1559,1561,1564,1566],{"class":432,"line":1090},[430,1536,1497],{"class":436},[430,1538,274],{"class":440},[430,1540,1541],{"class":436},"SigningOptions",[430,1543,274],{"class":440},[430,1545,1546],{"class":436},"SymmetricKey ",[430,1548,993],{"class":440},[430,1550,1079],{"class":436},[430,1552,274],{"class":440},[430,1554,1555],{"class":436},"Configuration",[430,1557,1558],{"class":440},"[",[430,1560,502],{"class":440},[430,1562,1563],{"class":505},"Jwt:SymmetricKey",[430,1565,502],{"class":440},[430,1567,1568],{"class":440},"];\n",[430,1570,1571],{"class":432,"line":1102},[430,1572,1573],{"class":440},"    };\n",[430,1575,1577],{"class":432,"line":1576},11,[430,1578,671],{"class":440},[256,1580,1581,1583,1584,537,1587,537,1590,537,1593,1125,1596,1599,1600,274],{},[259,1582,911],{}," then also maps ",[259,1585,1586],{},"\u002Fauth\u002Fcreate",[259,1588,1589],{},"\u002Fauth\u002Frefresh",[259,1591,1592],{},"\u002Fauth\u002Fverify",[259,1594,1595],{},"\u002Fauth\u002Flogout",[259,1597,1598],{},"\u002Fauth\u002FcsrfToken",". Signing keys, algorithms, and lifetimes: ",[271,1601,169],{"href":1602},"\u002Fmodules\u002Fjwt\u002F",[276,1604,1012],{"id":1605},"passkeys",[256,1607,1608,1610,1611,1614,1615,755,1618,1621,1622,1624],{},[259,1609,265],{}," does not map passkey routes. The .NET 10 Blazor Identity template has passkey pages, and its ",[259,1612,1613],{},"MapAdditionalIdentityEndpoints"," posts to ",[259,1616,1617],{},"\u002FAccount\u002FPasskeyCreationOptions",[259,1619,1620],{},"\u002FAccount\u002FPasskeyRequestOptions",". Those routes belong to that template. They are not ",[259,1623,265],{},", and they are not a passkey register, login, and credential API for a separate client.",[256,1626,1627,1628,1631,1632,1635,1636,1639,1640,1643,1644,1646,1647,1650,1651,274],{},"AuthEndpoints maps that API. The 3.x facade turns it on by default under ",[259,1629,1630],{},"{PasskeyPath}\u002Fpasskeys"," (",[259,1633,1634],{},"\u002Faccount\u002Fpasskeys","). In Production set ",[259,1637,1638],{},"Passkeys.ServerDomain",", or set ",[259,1641,1642],{},"Passkeys.Enabled"," to false to skip passkey services and routes. The password facade maps passkeys only when ",[259,1645,1638],{}," is set, under ",[259,1648,1649],{},"\u002Fauth\u002Fpasskeys",". See ",[271,1652,23],{"href":1375},[421,1654,1656],{"className":423,"code":1655,"language":425,"meta":426,"style":426},"builder.Services.AddAuthEndpoints\u003CAppUser, AppDbContext>(o =>\n{\n    o.Passkeys.ServerDomain = \"example.com\";\n});\n",[259,1657,1658,1684,1688,1710],{"__ignoreMap":426},[430,1659,1660,1662,1664,1666,1668,1670,1672,1674,1676,1678,1680,1682],{"class":432,"line":433},[430,1661,437],{"class":436},[430,1663,274],{"class":440},[430,1665,951],{"class":436},[430,1667,274],{"class":440},[430,1669,956],{"class":452},[430,1671,456],{"class":440},[430,1673,460],{"class":459},[430,1675,963],{"class":440},[430,1677,966],{"class":459},[430,1679,969],{"class":440},[430,1681,972],{"class":459},[430,1683,975],{"class":440},[430,1685,1686],{"class":432,"line":446},[430,1687,980],{"class":440},[430,1689,1690,1692,1694,1696,1698,1700,1702,1704,1706,1708],{"class":432,"line":466},[430,1691,985],{"class":436},[430,1693,274],{"class":440},[430,1695,1012],{"class":436},[430,1697,274],{"class":440},[430,1699,1431],{"class":436},[430,1701,993],{"class":440},[430,1703,996],{"class":440},[430,1705,1438],{"class":505},[430,1707,502],{"class":440},[430,1709,1003],{"class":440},[430,1711,1712],{"class":432,"line":482},[430,1713,671],{"class":440},[256,1715,1716,1717,537,1720,537,1723,1726,1727,529,1729,1731,1732,1735,1736,1739,1740,1743,1744,755,1747,274],{},"Mapped routes include ",[259,1718,1719],{},"POST \u002Faccount\u002Fpasskeys\u002Fregister",[259,1721,1722],{},"POST \u002Faccount\u002Fpasskeys\u002Flogin",[259,1724,1725],{},"GET \u002Faccount\u002Fpasskeys\u002F",", and add, rename, and delete. Passkey sign-in skips two-factor authentication. With no session argument, the completer follows Identity bearer query flags (",[259,1728,528],{},[259,1730,532],{},"), not cookie-facade ",[259,1733,1734],{},"LoginCookie",". Pass ",[259,1737,1738],{},"AuthEndpointsSession.Jwt"," when passkey sign-in should issue a JWT. Route table and ceremony: ",[271,1741,174],{"href":1742},"\u002Fmodules\u002Fpasskeys\u002F",". Client steps: ",[271,1745,51],{"href":1746},"\u002Fguides\u002Fregistration\u002F#register-with-a-passkey",[271,1748,56],{"href":1749},"\u002Fguides\u002Fsign-in\u002F#sign-in-with-a-passkey",[276,1751,1753],{"id":1752},"when-mapidentityapi-is-enough","When MapIdentityApi is enough",[256,1755,1756,1757,1759],{},"Use ",[259,1758,265],{}," when its ten routes, and a logout handler you write, cover the app. Use AuthEndpoints when you need a logout route, a prefix with only some modules, a JWT access token, or passkey endpoints.",[276,1761,1763],{"id":1762},"related","Related",[1765,1766,1767,1772,1777,1781,1785,1790,1794,1798],"ul",{},[1768,1769,1770],"li",{},[271,1771,231],{"href":273},[1768,1773,1774],{},[271,1775,226],{"href":1776},"\u002Fconcepts\u002Fcompare\u002F",[1768,1778,1779],{},[271,1780,61],{"href":575},[1768,1782,1783],{},[271,1784,23],{"href":1375},[1768,1786,1787],{},[271,1788,121],{"href":1789},"\u002Fcomposables\u002F",[1768,1791,1792],{},[271,1793,169],{"href":1602},[1768,1795,1796],{},[271,1797,174],{"href":1742},[1768,1799,1800],{},[271,1801,246],{"href":1802},"\u002Fconcepts\u002Ffaq\u002F",[1804,1805,1806],"style",{},"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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}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}",{"title":426,"searchDepth":433,"depth":446,"links":1808},[1809,1810,1811,1812,1813,1814,1815],{"id":278,"depth":446,"text":279},{"id":548,"depth":446,"text":549},{"id":683,"depth":446,"text":684},{"id":1236,"depth":446,"text":1237},{"id":1605,"depth":446,"text":1012},{"id":1752,"depth":446,"text":1753},{"id":1762,"depth":446,"text":1763},"MapIdentityApi alternative for ASP.NET Core when you need logout, chosen routes, JWT, or passkey endpoints.","md",null,{},{"icon":239},{"title":236,"description":1816},"LDua5LT-0EIcCNPPb-f5Qc9MZA7RBLhaOkzwnC91K6Q",[1824,1826],{"title":231,"path":232,"stem":233,"description":1825,"icon":234,"children":-1},"Side-by-side register, login, password reset, and 2FA for MapIdentityApi and the AuthEndpoints facade.",{"title":241,"path":242,"stem":243,"description":1827,"icon":244,"children":-1},"How AuthEndpoints protects sign-in and account changes, and which trade-offs it leaves to the host.",1792054259861]