[{"data":1,"prerenderedAt":1392},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Fsign-in":203,"\u002Fguides\u002Fsign-in-surround":1387},[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":46,"body":205,"description":1380,"extension":1381,"links":1382,"meta":1383,"navigation":1384,"path":47,"seo":1385,"stem":48,"__hash__":1386},"docs\u002F2.guides\u002F03.sign-in.md",{"type":206,"value":207,"toc":1366},"minimark",[208,243,248,426,442,446,472,595,599,613,645,659,674,678,705,787,792,822,831,834,840,866,869,884,889,898,914,927,931,945,950,962,967,1151,1155,1163,1225,1237,1242,1246,1293,1297,1300,1323,1327,1362],[209,210,211,212,216,217,220,221,216,224,220,227,216,230,233,234,237,238,242],"p",{},"Pick the sign-in method from the table, then follow its section. The examples use the facade defaults: ",[213,214,215],"code",{},"IdentityPath"," is ",[213,218,219],{},"\u002Fidentity",", ",[213,222,223],{},"PasskeyPath",[213,225,226],{},"\u002Faccount",[213,228,229],{},"Jwt.Path",[213,231,232],{},"\u002Fauth",", and the host maps external sign-in under ",[213,235,236],{},"\u002Fauth\u002Fexternal",". To pick a stack for your client, see ",[239,240,23],"a",{"href":241},"\u002Fgetting-started\u002Fchoose-a-sign-in-stack\u002F",".",[244,245,247],"h2",{"id":246},"compare-the-sign-in-methods","Compare the sign-in methods",[249,250,251,273],"table",{},[252,253,254],"thead",{},[255,256,257,261,264,267,270],"tr",{},[258,259,260],"th",{},"Method",[258,262,263],{},"Endpoints",[258,265,266],{},"Result",[258,268,269],{},"CSRF",[258,271,272],{},"Two-factor",[274,275,276,311,340,380,405],"tbody",{},[255,277,278,286,291,298,301],{},[279,280,281,285],"td",{},[239,282,284],{"href":283},"#sign-in-with-a-password-and-a-cookie","Password, cookie"," (facade default)",[279,287,288],{},[213,289,290],{},"POST \u002Fidentity\u002Flogin",[279,292,293,294,297],{},"Application cookie, empty ",[213,295,296],{},"200"," body",[279,299,300],{},"No",[279,302,303,306,307,310],{},[213,304,305],{},"401"," with title ",[213,308,309],{},"RequiresTwoFactor",", or send the code in the first request",[255,312,313,319,326,332,334],{},[279,314,315],{},[239,316,318],{"href":317},"#sign-in-with-a-password-and-identity-bearer-tokens","Password, Identity bearer",[279,320,321,220,323],{},[213,322,290],{},[213,324,325],{},"POST \u002Fidentity\u002Frefresh",[279,327,328,331],{},[213,329,330],{},"AccessTokenResponse"," JSON",[279,333,300],{},[279,335,336,306,338],{},[213,337,305],{},[213,339,309],{},[255,341,342,348,356,362,372],{},[279,343,344],{},[239,345,347],{"href":346},"#sign-in-with-a-password-and-a-jwt","Password, JWT",[279,349,350,220,353],{},[213,351,352],{},"POST \u002Fauth\u002Fcreate",[213,354,355],{},"POST \u002Fauth\u002Frefresh",[279,357,358,361],{},[213,359,360],{},"{ accessToken, tokenType }"," and an HttpOnly refresh cookie",[279,363,364,367,368,371],{},[213,365,366],{},"create",": no. ",[213,369,370],{},"refresh",": yes.",[279,373,374,376,377],{},[213,375,305],{}," with the extension ",[213,378,379],{},"requiresTwoFactor: true",[255,381,382,388,396,399,402],{},[279,383,384],{},[239,385,387],{"href":386},"#sign-in-with-a-passkey","Passkey",[279,389,390,220,393],{},[213,391,392],{},"POST \u002Faccount\u002Fpasskeys\u002FrequestOptions",[213,394,395],{},"POST \u002Faccount\u002Fpasskeys\u002Flogin",[279,397,398],{},"Cookie (with a query flag), Identity bearer tokens (no flag), or a JWT (JWT completer)",[279,400,401],{},"Yes",[279,403,404],{},"Skipped",[255,406,407,413,419,422,424],{},[279,408,409],{},[239,410,412],{"href":411},"#sign-in-with-github-or-google","GitHub or Google",[279,414,415,418],{},[213,416,417],{},"GET \u002Fauth\u002Fexternal\u002Flogin\u002F{provider}",", then the callback",[279,420,421],{},"Persistent application cookie, or a JWT refresh cookie",[279,423,300],{},[279,425,404],{},[209,427,428,429,432,433,435,436,438,439,242],{},"Every login request uses the ",[213,430,431],{},"AuthEndpoints.Login"," rate limit. JWT ",[213,434,355],{}," uses it too. Identity bearer ",[213,437,325],{}," has no rate limit. See ",[239,440,172],{"href":441},"\u002Fmodules\u002Frate-limits\u002F",[244,443,445],{"id":444},"sign-in-with-a-password-and-a-cookie","Sign in with a password and a cookie",[209,447,448,449,452,453,455,456,459,460,463,464,467,468,471],{},"The cookie facade maps ",[213,450,451],{},"LoginCookie"," on ",[213,454,290],{},". The body is Identity's ",[213,457,458],{},"LoginRequest",": ",[213,461,462],{},"{ \"email\", \"password\", \"twoFactorCode\"?, \"twoFactorRecoveryCode\"? }",". AuthEndpoints passes ",[213,465,466],{},"email"," to ",[213,469,470],{},"PasswordSignInAsync"," as the user name. Registration sets the user name to the email, so the email works.",[473,474,475,530,547],"ol",{},[476,477,478,479,482,483],"li",{},"Send the credentials with ",[213,480,481],{},"credentials: 'include'",". Login does not need a CSRF token.",[484,485,490],"pre",{"className":486,"code":487,"language":488,"meta":489,"style":489},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const response = await fetch('\u002Fidentity\u002Flogin', {\n  method: 'POST',\n  credentials: 'include',\n  headers: { 'Content-Type': 'application\u002Fjson' },\n  body: JSON.stringify({ email, password })\n});\n","js","",[213,491,492,500,506,512,518,524],{"__ignoreMap":489},[493,494,497],"span",{"class":495,"line":496},"line",1,[493,498,499],{},"const response = await fetch('\u002Fidentity\u002Flogin', {\n",[493,501,503],{"class":495,"line":502},2,[493,504,505],{},"  method: 'POST',\n",[493,507,509],{"class":495,"line":508},3,[493,510,511],{},"  credentials: 'include',\n",[493,513,515],{"class":495,"line":514},4,[493,516,517],{},"  headers: { 'Content-Type': 'application\u002Fjson' },\n",[493,519,521],{"class":495,"line":520},5,[493,522,523],{},"  body: JSON.stringify({ email, password })\n",[493,525,527],{"class":495,"line":526},6,[493,528,529],{},"});\n",[476,531,532,533,536,537,539,540,543,544,242],{},"To keep the cookie after the browser closes, add ",[213,534,535],{},"?useSessionCookies=false",". ",[213,538,451],{}," reads only ",[213,541,542],{},"useSessionCookies",". It ignores ",[213,545,546],{},"useCookies",[476,548,549,550],{},"Check the response:",[551,552,553,566,577,589],"ul",{},[476,554,555,557,558,561,562,565],{},[213,556,296],{}," with an empty body and a ",[213,559,560],{},"Set-Cookie"," header for ",[213,563,564],{},".AspNetCore.Identity.Application",": the user is signed in.",[476,567,568,306,570,572,573,242],{},[213,569,305],{},[213,571,309],{},": ask for a code. See ",[239,574,576],{"href":575},"#enter-a-two-factor-code-or-a-recovery-code","Enter a two-factor code or a recovery code",[476,578,579,306,581,584,585,588],{},[213,580,305],{},[213,582,583],{},"Unauthorized"," and detail ",[213,586,587],{},"Invalid credentials.",": the password is wrong, the account is locked out, or the email is not confirmed. AuthEndpoints returns one response for all three so that it does not reveal which one applies.",[476,590,591,594],{},[213,592,593],{},"429",": the rate limit rejected the request.",[244,596,598],{"id":597},"sign-in-with-a-password-and-identity-bearer-tokens","Sign in with a password and Identity bearer tokens",[209,600,601,602,605,606,609,610,242],{},"Use this method for native and mobile clients. Turn it on with ",[213,603,604],{},"AddAuthEndpoints\u003CTUser, TContext>(AuthEndpointsSignIn.IdentityBearer, ...)",", or compose ",[213,607,608],{},"AddBearerAuthEndpoints"," and ",[213,611,612],{},"MapBearerAuthEndpoints",[473,614,615,624,637],{},[476,616,617,618,620,621,623],{},"Send the same ",[213,619,458],{}," body to ",[213,622,290],{}," without query flags.",[476,625,626,627,630,631,633,634,242],{},"On success, read ",[213,628,629],{},"{ \"tokenType\", \"accessToken\", \"expiresIn\", \"refreshToken\" }"," from the ",[213,632,296],{}," body. Send the access token as ",[213,635,636],{},"Authorization: Bearer \u003CaccessToken>",[476,638,639,640,467,643,242],{},"To get a new access token, send ",[213,641,642],{},"{ \"refreshToken\" }",[213,644,325],{},[209,646,647,650,651,654,655,306,657,242],{},[213,648,649],{},"useCookies=true"," on this login sets a persistent application cookie instead of returning tokens. ",[213,652,653],{},"useSessionCookies=true"," sets a session cookie. The 2FA challenge is the same as cookie login: ",[213,656,305],{},[213,658,309],{},[660,661,664],"callout",{"color":662,"icon":663},"warning","i-lucide-triangle-alert",[209,665,666,667,670,671,242],{},"The bearer facade maps no ",[213,668,669],{},"\u002FcsrfToken"," route, but passkey ceremonies still need a CSRF token. To use passkeys on a bearer host, map an antiforgery token endpoint yourself. See ",[239,672,18],{"href":673},"\u002Fgetting-started\u002Fquick-start\u002F#native-and-mobile",[244,675,677],{"id":676},"sign-in-with-a-password-and-a-jwt","Sign in with a password and a JWT",[209,679,680,681,609,684,605,687,609,690,693,694,697,698,701,702,242],{},"Turn on JWT with ",[213,682,683],{},"o.Jwt.Enabled = true",[213,685,686],{},"o.Jwt.Configure",[213,688,689],{},"AddJwtEndpoints",[213,691,692],{},"MapJwtAuthEndpoints",". Call ",[213,695,696],{},"modelBuilder.UseRefreshToken()"," on your ",[213,699,700],{},"DbContext"," and add a migration. See ",[239,703,140],{"href":704},"\u002Fmodules\u002Fjwt\u002F",[473,706,707,752,770],{},[476,708,709,710,467,712,714,715,717,718,720,721],{},"Send ",[213,711,462],{},[213,713,352],{}," with ",[213,716,481],{},". The ",[213,719,466],{}," field also accepts a user name.",[484,722,724],{"className":486,"code":723,"language":488,"meta":489,"style":489},"const { accessToken } = await fetch('\u002Fauth\u002Fcreate', {\n  method: 'POST',\n  credentials: 'include',\n  headers: { 'Content-Type': 'application\u002Fjson' },\n  body: JSON.stringify({ email, password })\n}).then(r => r.json());\n",[213,725,726,731,735,739,743,747],{"__ignoreMap":489},[493,727,728],{"class":495,"line":496},[493,729,730],{},"const { accessToken } = await fetch('\u002Fauth\u002Fcreate', {\n",[493,732,733],{"class":495,"line":502},[493,734,505],{},[493,736,737],{"class":495,"line":508},[493,738,511],{},[493,740,741],{"class":495,"line":514},[493,742,517],{},[493,744,745],{"class":495,"line":520},[493,746,523],{},[493,748,749],{"class":495,"line":526},[493,750,751],{},"}).then(r => r.json());\n",[476,753,754,755,757,758,761,762,765,766,769],{},"On success, the ",[213,756,296],{}," body is ",[213,759,760],{},"{ \"accessToken\", \"tokenType\": \"Bearer\" }",". The response also sets the ",[213,763,764],{},"AuthEndpoints.Jwt.RefreshToken"," cookie. That cookie is HttpOnly, ",[213,767,768],{},"SameSite=Strict",", and lasts 14 days.",[476,771,772,773,775,776,779,780,783,784,242],{},"To get a new access token, call ",[213,774,355],{}," with the cookie and a CSRF token from ",[213,777,778],{},"GET \u002Fauth\u002FcsrfToken",". The body is ",[213,781,782],{},"{ \"accessToken\" }",", with no ",[213,785,786],{},"tokenType",[209,788,789,791],{},[213,790,366],{}," returns these errors:",[551,793,794,807,815],{},[476,795,796,799,800,802,803,806],{},[213,797,798],{},"400 { \"error\": \"invalid_request\", ... }"," when ",[213,801,466],{}," or ",[213,804,805],{},"password"," is missing. This body is not problem details.",[476,808,809,811,812,814],{},[213,810,305],{}," with detail ",[213,813,587],{}," for a wrong password, a lockout, or an unconfirmed email.",[476,816,817,376,819,821],{},[213,818,305],{},[213,820,379],{}," when 2FA is on and the request has no code.",[209,823,824,826,827,830],{},[213,825,370],{}," returns ",[213,828,829],{},"400 { \"errors\": [...] }"," when the cookie is missing, expired, revoked, or reused.",[244,832,576],{"id":833},"enter-a-two-factor-code-or-a-recovery-code",[209,835,836,837,242],{},"These steps apply to all three password methods. To turn 2FA on, see ",[239,838,56],{"href":839},"\u002Fguides\u002Ftwo-factor\u002F",[473,841,842,845,856],{},[476,843,844],{},"Send the email and password.",[476,846,847,848,850,851,853,854,242],{},"If the response is the 2FA challenge, ask the user for a 6-digit authenticator code or a recovery code. Cookie and Identity bearer login return title ",[213,849,309],{},". JWT ",[213,852,366],{}," returns the extension ",[213,855,379],{},[476,857,858,859,802,862,865],{},"Send the same request again with ",[213,860,861],{},"twoFactorCode",[213,863,864],{},"twoFactorRecoveryCode"," added.",[209,867,868],{},"If the client already has the code, send it in the first request. A valid code succeeds in one round trip.",[209,870,871,872,811,874,876,877,879,880,883],{},"A wrong code on cookie or Identity bearer login returns ",[213,873,305],{},[213,875,587],{}," JWT ",[213,878,366],{}," returns detail ",[213,881,882],{},"Invalid two factor code."," for a wrong authenticator code, and the Identity error description for a wrong recovery code.",[885,886,888],"h3",{"id":887},"remembered-browsers","Remembered browsers",[209,890,891,892,894,895,897],{},"A persistent cookie login (",[213,893,535],{},") with a valid ",[213,896,861],{}," sets the Identity two-factor remember-client cookie. Later password logins from that browser skip the 2FA challenge. These logins do not set the cookie:",[551,899,900,903,909],{},[476,901,902],{},"A session cookie login (the default).",[476,904,905,906,908],{},"A login with ",[213,907,864],{},". Each recovery code works once.",[476,910,911,912,242],{},"JWT ",[213,913,352],{},[209,915,916,917,714,920,923,924,242],{},"To clear the cookie, send ",[213,918,919],{},"POST \u002Fidentity\u002Fmanage\u002F2fa",[213,921,922],{},"{ \"forgetMachine\": true }",", or call ",[213,925,926],{},"POST \u002Fidentity\u002Flogout",[244,928,930],{"id":929},"sign-in-with-a-passkey","Sign in with a passkey",[209,932,933,934,937,938,714,941,944],{},"Passkeys are on by default. The default completer is ",[213,935,936],{},"IdentityPasskeySignInCompleter",". To get a JWT instead, register ",[213,939,940],{},"JwtPasskeySignInCompleter\u003CTUser>",[213,942,943],{},"AddPasskeySignInCompleter",". Turning on JWT does not select that completer for you.",[660,946,947],{"color":662,"icon":663},[209,948,949],{},"Passkey sign-in skips two-factor authentication. A user who turned on 2FA can sign in with a passkey alone.",[660,951,952],{"color":662,"icon":663},[209,953,954,955,958,959,242],{},"Use AuthEndpoints 3.1.1 or later. In 3.1.0, when JWT is not turned on, passkey registration and passkey sign-in return ",[213,956,957],{},"500",". So does any other CSRF-protected endpoint called without a session. To upgrade, run ",[213,960,961],{},"dotnet add package AuthEndpoints --version 3.1.1",[209,963,709,964,966],{},[213,965,481],{}," and the CSRF header on both requests. The ceremony state lives in a cookie.",[473,968,969,987,994,1105],{},[476,970,971,972,974,975,978,979,982,983,986],{},"Get request options from ",[213,973,392],{},". Send ",[213,976,977],{},"{}"," for a discoverable credential, or ",[213,980,981],{},"{ \"email\" }"," to sign in identifier-first. An email lets the response reveal through ",[213,984,985],{},"allowCredentials"," that the account has passkeys.",[476,988,989,990,993],{},"Call ",[213,991,992],{},"navigator.credentials.get",". If the user cancels, stop.",[476,995,996,997,714,999,242,1002,1026],{},"Send the credential to ",[213,998,395],{},[213,1000,1001],{},"{ \"credentialJson\" }",[551,1003,1004,1021],{},[476,1005,1006,1007,1010,1011,1014,1015,1018,1019,242],{},"On the cookie facade, always add ",[213,1008,1009],{},"?useSessionCookies=true"," for a session cookie or ",[213,1012,1013],{},"?useCookies=true"," for a persistent cookie. These flags follow Identity bearer ",[213,1016,1017],{},"Login",", not ",[213,1020,451],{},[476,1022,1023,1024,242],{},"With no flag, the default completer returns an Identity bearer ",[213,1025,330],{},[484,1027,1029],{"className":486,"code":1028,"language":488,"meta":489,"style":489},"const headers = { 'Content-Type': 'application\u002Fjson', 'RequestVerificationToken': csrfToken };\n\nconst options = await fetch('\u002Faccount\u002Fpasskeys\u002FrequestOptions', {\n  method: 'POST', credentials: 'include', headers, body: '{}'\n}).then(r => r.json());\n\nconst credential = await navigator.credentials.get({\n  publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options)\n});\n\nconst response = await fetch('\u002Faccount\u002Fpasskeys\u002Flogin?useSessionCookies=true', {\n  method: 'POST', credentials: 'include', headers,\n  body: JSON.stringify({ credentialJson: JSON.stringify(credential) })\n});\n",[213,1030,1031,1036,1042,1047,1052,1056,1060,1066,1072,1077,1082,1088,1094,1100],{"__ignoreMap":489},[493,1032,1033],{"class":495,"line":496},[493,1034,1035],{},"const headers = { 'Content-Type': 'application\u002Fjson', 'RequestVerificationToken': csrfToken };\n",[493,1037,1038],{"class":495,"line":502},[493,1039,1041],{"emptyLinePlaceholder":1040},true,"\n",[493,1043,1044],{"class":495,"line":508},[493,1045,1046],{},"const options = await fetch('\u002Faccount\u002Fpasskeys\u002FrequestOptions', {\n",[493,1048,1049],{"class":495,"line":514},[493,1050,1051],{},"  method: 'POST', credentials: 'include', headers, body: '{}'\n",[493,1053,1054],{"class":495,"line":520},[493,1055,751],{},[493,1057,1058],{"class":495,"line":526},[493,1059,1041],{"emptyLinePlaceholder":1040},[493,1061,1063],{"class":495,"line":1062},7,[493,1064,1065],{},"const credential = await navigator.credentials.get({\n",[493,1067,1069],{"class":495,"line":1068},8,[493,1070,1071],{},"  publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options)\n",[493,1073,1075],{"class":495,"line":1074},9,[493,1076,529],{},[493,1078,1080],{"class":495,"line":1079},10,[493,1081,1041],{"emptyLinePlaceholder":1040},[493,1083,1085],{"class":495,"line":1084},11,[493,1086,1087],{},"const response = await fetch('\u002Faccount\u002Fpasskeys\u002Flogin?useSessionCookies=true', {\n",[493,1089,1091],{"class":495,"line":1090},12,[493,1092,1093],{},"  method: 'POST', credentials: 'include', headers,\n",[493,1095,1097],{"class":495,"line":1096},13,[493,1098,1099],{},"  body: JSON.stringify({ credentialJson: JSON.stringify(credential) })\n",[493,1101,1103],{"class":495,"line":1102},14,[493,1104,529],{},[476,1106,549,1107],{},[551,1108,1109,1114,1122,1129,1142],{},[476,1110,1111,1113],{},[213,1112,296],{}," with an empty body and a cookie: the user is signed in.",[476,1115,1116,714,1118,1121],{},[213,1117,296],{},[213,1119,1120],{},"{ \"accessToken\", \"tokenType\" }"," and a refresh cookie: the JWT completer signed the user in.",[476,1123,1124,811,1126,1128],{},[213,1125,305],{},[213,1127,587],{},": the account is locked out or the email is not confirmed.",[476,1130,1131,306,1134,1137,1138,1141],{},[213,1132,1133],{},"400",[213,1135,1136],{},"Invalid Credential",": the assertion failed or ",[213,1139,1140],{},"credentialJson"," was empty.",[476,1143,1144,1146,1147,1150],{},[213,1145,1133],{}," validation problem ",[213,1148,1149],{},"InvalidPasskeyState",": no ceremony was underway. Start again from step 1.",[244,1152,1154],{"id":1153},"sign-in-with-github-or-google","Sign in with GitHub or Google",[209,1156,1157,1158,1162],{},"Set up the packages and routes as in ",[239,1159,1161],{"href":1160},"\u002Fguides\u002Fregistration\u002F#register-with-github-or-google","Register with GitHub or Google",". The same callback signs users in.",[473,1164,1165,1177,1192],{},[476,1166,1167,1168],{},"Send the browser to the login route with a top-level navigation:",[484,1169,1171],{"className":486,"code":1170,"language":488,"meta":489,"style":489},"window.location.assign('\u002Fauth\u002Fexternal\u002Flogin\u002Fgoogle?returnUrl=' + encodeURIComponent('\u002Fdashboard'));\n",[213,1172,1173],{"__ignoreMap":489},[493,1174,1175],{"class":495,"line":496},[493,1176,1170],{},[476,1178,1179,1180,1183,1184,1187,1188,1191],{},"The callback signs in a user who already has this provider login. It refuses a local user with the same email and no link, with the error ",[213,1181,1182],{},"auto_link_disabled",". With ",[213,1185,1186],{},"AutoLinkByEmail"," set to ",[213,1189,1190],{},"true",", it links that user only when the provider email is verified and the local email is confirmed.",[476,1193,1194,1195,467,1198,1201,1202],{},"On success, the response is a ",[213,1196,1197],{},"302",[213,1199,1200],{},"returnUrl",":",[551,1203,1204,1216],{},[476,1205,1206,1209,1210,1213,1214,242],{},[213,1207,1208],{},"CookieExternalLoginCompleter"," (the default) sets the application cookie. The cookie is persistent because ",[213,1211,1212],{},"IsPersistent"," defaults to ",[213,1215,1190],{},[476,1217,1218,1221,1222,1224],{},[213,1219,1220],{},"JwtExternalLoginCompleter"," sets the JWT refresh cookie. Call ",[213,1223,355],{}," with a CSRF token to get the access token.",[209,1226,1227,1229,1230,1233,1234,242],{},[213,1228,1200],{}," must be a rooted local path, or an absolute URL whose origin is in ",[213,1231,1232],{},"AllowedReturnUrlOrigins",". Any other value falls back to ",[213,1235,1236],{},"DefaultReturnUrl",[660,1238,1239],{"color":662,"icon":663},[209,1240,1241],{},"OAuth sign-in skips two-factor authentication with both built-in completers.",[244,1243,1245],{"id":1244},"help-a-user-who-cannot-sign-in","Help a user who cannot sign in",[551,1247,1248,1265,1271,1284],{},[476,1249,1250,1254,1255,1258,1259,1261,1262,242],{},[1251,1252,1253],"strong",{},"Forgotten password."," ",[213,1256,1257],{},"POST \u002Fidentity\u002FforgotPassword"," always returns ",[213,1260,296],{},". AuthEndpoints sends mail only to a confirmed account. See ",[239,1263,61],{"href":1264},"\u002Fguides\u002Freset-password\u002F",[476,1266,1267,1270],{},[1251,1268,1269],{},"Lost authenticator."," The user signs in with a recovery code instead of a TOTP code.",[476,1272,1273,1276,1277,1280,1281,242],{},[1251,1274,1275],{},"Locked out."," Lockout uses Identity's defaults. Change them with ",[213,1278,1279],{},"ConfigureIdentity",". See ",[239,1282,158],{"href":1283},"\u002Fmodules\u002Fconfiguration\u002F",[476,1285,1286,1289,1290,242],{},[1251,1287,1288],{},"Unconfirmed email."," The user opens the confirmation link first. See ",[239,1291,41],{"href":1292},"\u002Fguides\u002Fregistration\u002F",[244,1294,1296],{"id":1295},"what-sign-in-does-not-support","What sign-in does not support",[209,1298,1299],{},"AuthEndpoints does not include these features:",[551,1301,1302,1305,1308,1311,1314,1317,1320],{},[476,1303,1304],{},"Sign-in with a magic link or an emailed one-time code.",[476,1306,1307],{},"Two-factor codes by SMS or email. Identity has an email token provider, but no endpoint exposes it.",[476,1309,1310],{},"A passkey as a second factor after a password. Passkeys are a first factor only.",[476,1312,1313],{},"Built-in Apple or Microsoft providers.",[476,1315,1316],{},"GitHub or Google sign-in that returns Identity bearer tokens.",[476,1318,1319],{},"An endpoint that lists or revokes a user's other sessions.",[476,1321,1322],{},"An admin endpoint that unlocks an account.",[244,1324,1326],{"id":1325},"related","Related",[551,1328,1329,1333,1338,1342,1347,1352,1357],{},[476,1330,1331],{},[239,1332,41],{"href":1292},[476,1334,1335],{},[239,1336,51],{"href":1337},"\u002Fguides\u002Fsign-out\u002F",[476,1339,1340],{},[239,1341,56],{"href":839},[476,1343,1344],{},[239,1345,86],{"href":1346},"\u002Fguides\u002Fbrowser-clients\u002F",[476,1348,1349],{},[239,1350,163],{"href":1351},"\u002Fmodules\u002Fcsrf\u002F",[476,1353,1354],{},[239,1355,167],{"href":1356},"\u002Fmodules\u002Ferrors\u002F",[476,1358,1359],{},[239,1360,194],{"href":1361},"\u002Fconcepts\u002Fsecurity-model\u002F",[1363,1364,1365],"style",{},"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);}",{"title":489,"searchDepth":496,"depth":502,"links":1367},[1368,1369,1370,1371,1372,1375,1376,1377,1378,1379],{"id":246,"depth":502,"text":247},{"id":444,"depth":502,"text":445},{"id":597,"depth":502,"text":598},{"id":676,"depth":502,"text":677},{"id":833,"depth":502,"text":576,"children":1373},[1374],{"id":887,"depth":508,"text":888},{"id":929,"depth":502,"text":930},{"id":1153,"depth":502,"text":1154},{"id":1244,"depth":502,"text":1245},{"id":1295,"depth":502,"text":1296},{"id":1325,"depth":502,"text":1326},"Sign users in with a password, a passkey, or GitHub or Google, and handle two-factor codes and recovery codes.","md",null,{},{"icon":49},{"title":46,"description":1380},"pW1z6mPUy7CmT7TYX3b9MXOAsNi3eLF7gl44CMC88Kg",[1388,1390],{"title":41,"path":42,"stem":43,"description":1389,"icon":44,"children":-1},"Create accounts with an email and password, a passkey, or a GitHub or Google account.",{"title":51,"path":52,"stem":53,"description":1391,"icon":54,"children":-1},"Sign users out of the cookie, Identity bearer, and JWT stacks.",1791123626151]