[{"data":1,"prerenderedAt":3984},["ShallowReactive",2],{"navigation_docs":3,"-guides-email-auth":265,"-guides-email-auth-surround":3979},[4,35,49,89,117,164,193,235,253,257,261],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"/getting-started","1.getting-started",[10,15,20,25,30],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","/getting-started/introduction","1.getting-started/2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","/getting-started/installation","1.getting-started/3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","/getting-started/quick-start","1.getting-started/4.quick-start","i-lucide-rocket",{"title":26,"path":27,"stem":28,"icon":29},"Configuration","/getting-started/configuration","1.getting-started/5.configuration","i-lucide-sliders-horizontal",{"title":31,"path":32,"stem":33,"icon":34},"First Auth","/getting-started/first-auth","1.getting-started/6.first-auth","i-lucide-key-round",{"title":36,"path":37,"stem":38,"children":39,"page":6},"Migration","/migration","10.migration",[40,45],{"title":41,"path":42,"stem":43,"icon":44},"Migration depuis Firebase Auth","/migration/from-firebase","10.migration/1.from-firebase","i-lucide-arrow-right-left",{"title":46,"path":47,"stem":48,"icon":44},"Migration depuis Supabase Auth","/migration/from-supabase","10.migration/2.from-supabase",{"title":50,"path":51,"stem":52,"children":53,"page":6},"Core Concepts","/core-concepts","2.core-concepts",[54,59,64,69,74,79,84],{"title":55,"path":56,"stem":57,"icon":58},"Architecture","/core-concepts/architecture","2.core-concepts/1.architecture","i-lucide-layers",{"title":60,"path":61,"stem":62,"icon":63},"Providers","/core-concepts/providers","2.core-concepts/2.providers","i-lucide-plug",{"title":65,"path":66,"stem":67,"icon":68},"Sessions","/core-concepts/sessions","2.core-concepts/3.sessions","i-lucide-timer",{"title":70,"path":71,"stem":72,"icon":73},"Storage","/core-concepts/storage","2.core-concepts/4.storage","i-lucide-database",{"title":75,"path":76,"stem":77,"icon":78},"Reactivity","/core-concepts/reactivity","2.core-concepts/5.reactivity","i-lucide-activity",{"title":80,"path":81,"stem":82,"icon":83},"Callbacks","/core-concepts/callbacks","2.core-concepts/6.callbacks","i-lucide-shield-check",{"title":85,"path":86,"stem":87,"icon":88},"Events","/core-concepts/events","2.core-concepts/7.events","i-lucide-radio",{"title":60,"path":90,"stem":91,"children":92,"page":6},"/providers","3.providers",[93,97,101,105,109,113],{"title":94,"path":95,"stem":96},"Credentials Provider","/providers/credentials","3.providers/1.credentials",{"title":98,"path":99,"stem":100},"OAuth2 Provider","/providers/oauth2","3.providers/2.oauth2",{"title":102,"path":103,"stem":104},"Google Provider","/providers/google","3.providers/3.google",{"title":106,"path":107,"stem":108},"GitHub Provider","/providers/github","3.providers/4.github",{"title":110,"path":111,"stem":112},"Apple Provider","/providers/apple","3.providers/5.apple",{"title":114,"path":115,"stem":116},"Proxy OAuth Provider","/providers/proxy-oauth","3.providers/6.proxy-oauth",{"title":118,"path":119,"stem":120,"children":121,"page":6},"Guides","/guides","4.guides",[122,126,131,136,141,146,151,155,159],{"title":123,"path":124,"stem":125},"Email / Password Auth","/guides/email-auth","4.guides/1.email-auth",{"title":127,"path":128,"stem":129,"icon":130},"Custom OAuth2 Flow","/guides/oauth2-flow","4.guides/2.oauth2-flow","i-lucide-workflow",{"title":132,"path":133,"stem":134,"icon":135},"Deep Links & OAuth2 Callbacks","/guides/deep-links","4.guides/3.deep-links","i-lucide-link",{"title":137,"path":138,"stem":139,"icon":140},"Token Refresh","/guides/token-refresh","4.guides/4.token-refresh","i-lucide-refresh-cw",{"title":142,"path":143,"stem":144,"icon":145},"Multi-Account","/guides/multi-account","4.guides/5.multi-account","i-lucide-users",{"title":147,"path":148,"stem":149,"icon":150},"Route Protection","/guides/route-protection","4.guides/6.route-protection","i-lucide-lock",{"title":152,"path":153,"stem":154,"icon":63},"Custom Provider","/guides/custom-provider","4.guides/7.custom-provider",{"title":156,"path":157,"stem":158,"icon":73},"Custom Storage","/guides/custom-storage","4.guides/8.custom-storage",{"title":160,"path":161,"stem":162,"icon":163},"Testing","/guides/testing","4.guides/9.testing","i-lucide-flask-conical",{"title":165,"path":166,"stem":167,"children":168,"page":6},"Flutter","/flutter","5.flutter",[169,173,178,183,188],{"title":170,"path":171,"stem":172},"Flutter Setup","/flutter/setup","5.flutter/1.setup",{"title":174,"path":175,"stem":176,"icon":177},"Secure Storage","/flutter/secure-storage","5.flutter/2.secure-storage","i-lucide-vault",{"title":179,"path":180,"stem":181,"icon":182},"Widgets","/flutter/widgets","5.flutter/3.widgets","i-lucide-layout",{"title":184,"path":185,"stem":186,"icon":187},"Router Guard","/flutter/router-guard","5.flutter/4.router-guard","i-lucide-signpost",{"title":189,"path":190,"stem":191,"icon":192},"App Binding","/flutter/app-binding","5.flutter/5.app-binding","i-lucide-cpu",{"title":194,"path":195,"stem":196,"children":197,"page":6},"API Reference","/api-reference","6.api-reference",[198,202,206,211,216,221,225,230],{"title":199,"path":200,"stem":201},"AuthyraClient","/api-reference/authyra-client","6.api-reference/1.authyra-client",{"title":203,"path":204,"stem":205},"AuthyraInstance","/api-reference/authyra-instance","6.api-reference/2.authyra-instance",{"title":207,"path":208,"stem":209,"icon":210},"AccountManager","/api-reference/account-manager","6.api-reference/3.account-manager","i-lucide-users-round",{"title":212,"path":213,"stem":214,"icon":215},"AuthProvider","/api-reference/auth-provider","6.api-reference/4.auth-provider","i-lucide-plug-zap",{"title":217,"path":218,"stem":219,"icon":220},"AuthStorage","/api-reference/auth-storage","6.api-reference/5.auth-storage","i-lucide-hard-drive",{"title":222,"path":223,"stem":224,"icon":68},"AuthSession","/api-reference/auth-session","6.api-reference/6.auth-session",{"title":226,"path":227,"stem":228,"icon":229},"AuthState","/api-reference/auth-state","6.api-reference/7.auth-state","i-lucide-toggle-right",{"title":231,"path":232,"stem":233,"icon":234},"Exceptions","/api-reference/auth-exceptions","6.api-reference/8.auth-exceptions","i-lucide-triangle-alert",{"title":236,"path":237,"stem":238,"children":239,"page":6},"Examples","/examples","7.examples",[240,244,249],{"title":241,"path":242,"stem":243},"Flutter App Example","/examples/flutter-app","7.examples/1.flutter-app",{"title":245,"path":246,"stem":247,"icon":248},"Dart Backend","/examples/dart-backend","7.examples/2.dart-backend","i-lucide-server",{"title":250,"path":251,"stem":252,"icon":163},"Testing Setup","/examples/testing-setup","7.examples/3.testing-setup",{"title":254,"path":255,"stem":256},"Troubleshooting","/troubleshooting","8.troubleshooting",{"title":258,"path":259,"stem":260},"FAQ","/faq","9.faq",{"title":262,"path":263,"stem":264},"Changelog","/changelog","changelog",{"id":266,"title":123,"body":267,"description":3971,"extension":3972,"links":3973,"meta":3974,"navigation":557,"path":124,"seo":3975,"stem":125,"__hash__":3978},"docs/4.guides/1.email-auth.md",{"type":268,"value":269,"toc":3950},"minimark",[270,274,299,302,307,310,470,480,482,486,522,524,528,533,1008,1012,1015,1150,1152,1156,1159,1303,1307,1392,1394,1398,2316,2318,2322,2325,2623,2627,2883,2885,2889,2956,2959,3047,3049,3053,3082,3084,3087,3098,3922,3924,3928,3946],[271,272,273],"p",{},"This guide walks through a complete email/password setup with a JWT backend. By the end you'll have:",[275,276,277,286,289,296],"ul",{},[278,279,280,281,285],"li",{},"A configured ",[282,283,284],"code",{},"CredentialsProvider"," that talks to your API",[278,287,288],{},"A signed-in user with an access token and refresh token in the session",[278,290,291,292,295],{},"A ",[282,293,294],{},"StreamBuilder"," that reacts to auth state changes",[278,297,298],{},"Unit tests that run without a network connection",[300,301],"hr",{},[303,304,306],"h2",{"id":305},"backend-contract","Backend contract",[271,308,309],{},"Authyra doesn't care about your backend tech stack. It expects your sign-in endpoint to return a JSON body with at least:",[311,312,317],"pre",{"className":313,"code":314,"language":315,"meta":316,"style":316},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"id\":           \"usr_01j...\",\n  \"email\":        \"alice@example.com\",\n  \"name\":         \"Alice\",\n  \"accessToken\":  \"eyJhbGciOi...\",\n  \"refreshToken\": \"dGhpcyBpcyBh...\",\n  \"expiresAt\":    \"2026-03-01T12:00:00.000Z\"\n}\n","json","",[282,318,319,328,356,378,400,421,443,464],{"__ignoreMap":316},[320,321,324],"span",{"class":322,"line":323},"line",1,[320,325,327],{"class":326},"sMK4o","{\n",[320,329,331,334,338,341,344,347,351,353],{"class":322,"line":330},2,[320,332,333],{"class":326},"  \"",[320,335,337],{"class":336},"spNyl","id",[320,339,340],{"class":326},"\"",[320,342,343],{"class":326},":",[320,345,346],{"class":326},"           \"",[320,348,350],{"class":349},"sfazB","usr_01j...",[320,352,340],{"class":326},[320,354,355],{"class":326},",\n",[320,357,359,361,364,366,368,371,374,376],{"class":322,"line":358},3,[320,360,333],{"class":326},[320,362,363],{"class":336},"email",[320,365,340],{"class":326},[320,367,343],{"class":326},[320,369,370],{"class":326},"        \"",[320,372,373],{"class":349},"alice@example.com",[320,375,340],{"class":326},[320,377,355],{"class":326},[320,379,381,383,386,388,390,393,396,398],{"class":322,"line":380},4,[320,382,333],{"class":326},[320,384,385],{"class":336},"name",[320,387,340],{"class":326},[320,389,343],{"class":326},[320,391,392],{"class":326},"         \"",[320,394,395],{"class":349},"Alice",[320,397,340],{"class":326},[320,399,355],{"class":326},[320,401,403,405,408,410,412,414,417,419],{"class":322,"line":402},5,[320,404,333],{"class":326},[320,406,407],{"class":336},"accessToken",[320,409,340],{"class":326},[320,411,343],{"class":326},[320,413,333],{"class":326},[320,415,416],{"class":349},"eyJhbGciOi...",[320,418,340],{"class":326},[320,420,355],{"class":326},[320,422,424,426,429,431,433,436,439,441],{"class":322,"line":423},6,[320,425,333],{"class":326},[320,427,428],{"class":336},"refreshToken",[320,430,340],{"class":326},[320,432,343],{"class":326},[320,434,435],{"class":326}," \"",[320,437,438],{"class":349},"dGhpcyBpcyBh...",[320,440,340],{"class":326},[320,442,355],{"class":326},[320,444,446,448,451,453,455,458,461],{"class":322,"line":445},7,[320,447,333],{"class":326},[320,449,450],{"class":336},"expiresAt",[320,452,340],{"class":326},[320,454,343],{"class":326},[320,456,457],{"class":326},"    \"",[320,459,460],{"class":349},"2026-03-01T12:00:00.000Z",[320,462,463],{"class":326},"\"\n",[320,465,467],{"class":322,"line":466},8,[320,468,469],{"class":326},"}\n",[271,471,472,473,475,476,479],{},"If your backend doesn't return tokens (cookie session, opaque session), use ",[282,474,284],{}," instead of ",[282,477,478],{},".withTokens"," — see the cookie session variant in step 2 below.",[300,481],{},[303,483,485],{"id":484},"_1-install","1. Install",[311,487,492],{"className":488,"code":489,"filename":490,"language":491,"meta":316,"style":316},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dependencies:\n  authyra_flutter: ^0.1.0  # Flutter app\n  # or authyra: ^0.1.0    # Dart backend / tests only\n","pubspec.yaml","yaml",[282,493,494,503,517],{"__ignoreMap":316},[320,495,496,500],{"class":322,"line":323},[320,497,499],{"class":498},"swJcz","dependencies",[320,501,502],{"class":326},":\n",[320,504,505,508,510,513],{"class":322,"line":330},[320,506,507],{"class":498},"  authyra_flutter",[320,509,343],{"class":326},[320,511,512],{"class":349}," ^0.1.0",[320,514,516],{"class":515},"sHwdD","  # Flutter app\n",[320,518,519],{"class":322,"line":358},[320,520,521],{"class":515},"  # or authyra: ^0.1.0    # Dart backend / tests only\n",[300,523],{},[303,525,527],{"id":526},"_2-configure-the-provider","2. Configure the provider",[529,530,532],"h3",{"id":531},"jwt-backend-recommended","JWT backend (recommended)",[311,534,539],{"className":535,"code":536,"filename":537,"language":538,"meta":316,"style":316},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import 'package:authyra_flutter/authyra_flutter.dart';\n\nCredentialsProvider.withTokens(\n  id: 'email',\n  authorize: (creds) async {\n    final res = await myApi.post('/auth/login', body: {\n      'email':    creds!['email'],\n      'password': creds['password'],\n    });\n\n    if (res.statusCode == 401) return null; // wrong credentials\n    if (res.statusCode != 200) {\n      throw AuthenticationFailedException(\n        'Login failed: HTTP ${res.statusCode}',\n        providerName: 'email',\n      );\n    }\n\n    return AuthSignInResult(\n      user: AuthUser(\n        id:    res.data['id'],\n        email: res.data['email'],\n        name:  res.data['name'],\n      ),\n      accessToken:  res.data['accessToken'],\n      refreshToken: res.data['refreshToken'],\n      expiresAt:    DateTime.parse(res.data['expiresAt']),\n    );\n  },\n)\n","lib/auth/auth_provider.dart","dart",[282,540,541,553,559,575,587,604,642,666,683,691,696,728,748,759,785,797,805,811,816,827,840,863,884,906,913,934,955,986,994,1002],{"__ignoreMap":316},[320,542,543,547,550],{"class":322,"line":323},[320,544,546],{"class":545},"sbssI","import",[320,548,549],{"class":349}," 'package:authyra_flutter/authyra_flutter.dart'",[320,551,552],{"class":326},";\n",[320,554,555],{"class":322,"line":330},[320,556,558],{"emptyLinePlaceholder":557},true,"\n",[320,560,561,564,567,571],{"class":322,"line":358},[320,562,284],{"class":563},"sBMFI",[320,565,566],{"class":326},".",[320,568,570],{"class":569},"s2Zo4","withTokens",[320,572,574],{"class":573},"sTEyZ","(\n",[320,576,577,580,582,585],{"class":322,"line":380},[320,578,579],{"class":573},"  id",[320,581,343],{"class":326},[320,583,584],{"class":349}," 'email'",[320,586,355],{"class":326},[320,588,589,592,594,597,601],{"class":322,"line":402},[320,590,591],{"class":573},"  authorize",[320,593,343],{"class":326},[320,595,596],{"class":573}," (creds) ",[320,598,600],{"class":599},"s7zQu","async",[320,602,603],{"class":573}," {\n",[320,605,606,609,612,615,618,621,623,626,629,632,635,638,640],{"class":322,"line":423},[320,607,608],{"class":336},"    final",[320,610,611],{"class":573}," res ",[320,613,614],{"class":326},"=",[320,616,617],{"class":599}," await",[320,619,620],{"class":573}," myApi",[320,622,566],{"class":326},[320,624,625],{"class":569},"post",[320,627,628],{"class":573},"(",[320,630,631],{"class":349},"'/auth/login'",[320,633,634],{"class":326},",",[320,636,637],{"class":573}," body",[320,639,343],{"class":326},[320,641,603],{"class":573},[320,643,644,647,649,652,655,658,661,664],{"class":322,"line":445},[320,645,646],{"class":349},"      'email'",[320,648,343],{"class":326},[320,650,651],{"class":573},"    creds",[320,653,654],{"class":326},"!",[320,656,657],{"class":573},"[",[320,659,660],{"class":349},"'email'",[320,662,663],{"class":573},"]",[320,665,355],{"class":326},[320,667,668,671,673,676,679,681],{"class":322,"line":466},[320,669,670],{"class":349},"      'password'",[320,672,343],{"class":326},[320,674,675],{"class":573}," creds[",[320,677,678],{"class":349},"'password'",[320,680,663],{"class":573},[320,682,355],{"class":326},[320,684,686,689],{"class":322,"line":685},9,[320,687,688],{"class":573},"    })",[320,690,552],{"class":326},[320,692,694],{"class":322,"line":693},10,[320,695,558],{"emptyLinePlaceholder":557},[320,697,699,702,705,707,710,713,716,719,722,725],{"class":322,"line":698},11,[320,700,701],{"class":599},"    if",[320,703,704],{"class":573}," (res",[320,706,566],{"class":326},[320,708,709],{"class":573},"statusCode ",[320,711,712],{"class":326},"==",[320,714,715],{"class":545}," 401",[320,717,718],{"class":573},") ",[320,720,721],{"class":599},"return",[320,723,724],{"class":326}," null;",[320,726,727],{"class":515}," // wrong credentials\n",[320,729,731,733,735,737,739,742,745],{"class":322,"line":730},12,[320,732,701],{"class":599},[320,734,704],{"class":573},[320,736,566],{"class":326},[320,738,709],{"class":573},[320,740,741],{"class":326},"!=",[320,743,744],{"class":545}," 200",[320,746,747],{"class":573},") {\n",[320,749,751,754,757],{"class":322,"line":750},13,[320,752,753],{"class":599},"      throw",[320,755,756],{"class":563}," AuthenticationFailedException",[320,758,574],{"class":573},[320,760,762,765,768,772,774,777,780,783],{"class":322,"line":761},14,[320,763,764],{"class":349},"        'Login failed: HTTP ",[320,766,767],{"class":573},"${",[320,769,771],{"class":770},"sHdIc","res",[320,773,566],{"class":573},[320,775,776],{"class":770},"statusCode",[320,778,779],{"class":573},"}",[320,781,782],{"class":349},"'",[320,784,355],{"class":326},[320,786,788,791,793,795],{"class":322,"line":787},15,[320,789,790],{"class":573},"        providerName",[320,792,343],{"class":326},[320,794,584],{"class":349},[320,796,355],{"class":326},[320,798,800,803],{"class":322,"line":799},16,[320,801,802],{"class":573},"      )",[320,804,552],{"class":326},[320,806,808],{"class":322,"line":807},17,[320,809,810],{"class":573},"    }\n",[320,812,814],{"class":322,"line":813},18,[320,815,558],{"emptyLinePlaceholder":557},[320,817,819,822,825],{"class":322,"line":818},19,[320,820,821],{"class":599},"    return",[320,823,824],{"class":563}," AuthSignInResult",[320,826,574],{"class":573},[320,828,830,833,835,838],{"class":322,"line":829},20,[320,831,832],{"class":573},"      user",[320,834,343],{"class":326},[320,836,837],{"class":563}," AuthUser",[320,839,574],{"class":573},[320,841,843,846,848,851,853,856,859,861],{"class":322,"line":842},21,[320,844,845],{"class":573},"        id",[320,847,343],{"class":326},[320,849,850],{"class":573},"    res",[320,852,566],{"class":326},[320,854,855],{"class":573},"data[",[320,857,858],{"class":349},"'id'",[320,860,663],{"class":573},[320,862,355],{"class":326},[320,864,866,869,871,874,876,878,880,882],{"class":322,"line":865},22,[320,867,868],{"class":573},"        email",[320,870,343],{"class":326},[320,872,873],{"class":573}," res",[320,875,566],{"class":326},[320,877,855],{"class":573},[320,879,660],{"class":349},[320,881,663],{"class":573},[320,883,355],{"class":326},[320,885,887,890,892,895,897,899,902,904],{"class":322,"line":886},23,[320,888,889],{"class":573},"        name",[320,891,343],{"class":326},[320,893,894],{"class":573},"  res",[320,896,566],{"class":326},[320,898,855],{"class":573},[320,900,901],{"class":349},"'name'",[320,903,663],{"class":573},[320,905,355],{"class":326},[320,907,909,911],{"class":322,"line":908},24,[320,910,802],{"class":573},[320,912,355],{"class":326},[320,914,916,919,921,923,925,927,930,932],{"class":322,"line":915},25,[320,917,918],{"class":573},"      accessToken",[320,920,343],{"class":326},[320,922,894],{"class":573},[320,924,566],{"class":326},[320,926,855],{"class":573},[320,928,929],{"class":349},"'accessToken'",[320,931,663],{"class":573},[320,933,355],{"class":326},[320,935,937,940,942,944,946,948,951,953],{"class":322,"line":936},26,[320,938,939],{"class":573},"      refreshToken",[320,941,343],{"class":326},[320,943,873],{"class":573},[320,945,566],{"class":326},[320,947,855],{"class":573},[320,949,950],{"class":349},"'refreshToken'",[320,952,663],{"class":573},[320,954,355],{"class":326},[320,956,958,961,963,966,968,971,974,976,978,981,984],{"class":322,"line":957},27,[320,959,960],{"class":573},"      expiresAt",[320,962,343],{"class":326},[320,964,965],{"class":563},"    DateTime",[320,967,566],{"class":326},[320,969,970],{"class":569},"parse",[320,972,973],{"class":573},"(res",[320,975,566],{"class":326},[320,977,855],{"class":573},[320,979,980],{"class":349},"'expiresAt'",[320,982,983],{"class":573},"])",[320,985,355],{"class":326},[320,987,989,992],{"class":322,"line":988},28,[320,990,991],{"class":573},"    )",[320,993,552],{"class":326},[320,995,997,1000],{"class":322,"line":996},29,[320,998,999],{"class":573},"  }",[320,1001,355],{"class":326},[320,1003,1005],{"class":322,"line":1004},30,[320,1006,1007],{"class":573},")\n",[529,1009,1011],{"id":1010},"variant-cookie-session","Variant — cookie session",[271,1013,1014],{},"If your backend handles sessions server-side and only returns the user profile:",[311,1016,1018],{"className":535,"code":1017,"language":538,"meta":316,"style":316},"CredentialsProvider(\n  id: 'email',\n  authorize: (creds) async {\n    final res = await myApi.post('/auth/login', body: creds);\n    if (res.statusCode != 200) return null;\n    return AuthUser(id: res.data['id'], email: res.data['email']);\n  },\n)\n",[282,1019,1020,1026,1036,1048,1079,1100,1140,1146],{"__ignoreMap":316},[320,1021,1022,1024],{"class":322,"line":323},[320,1023,284],{"class":563},[320,1025,574],{"class":573},[320,1027,1028,1030,1032,1034],{"class":322,"line":330},[320,1029,579],{"class":573},[320,1031,343],{"class":326},[320,1033,584],{"class":349},[320,1035,355],{"class":326},[320,1037,1038,1040,1042,1044,1046],{"class":322,"line":358},[320,1039,591],{"class":573},[320,1041,343],{"class":326},[320,1043,596],{"class":573},[320,1045,600],{"class":599},[320,1047,603],{"class":573},[320,1049,1050,1052,1054,1056,1058,1060,1062,1064,1066,1068,1070,1072,1074,1077],{"class":322,"line":380},[320,1051,608],{"class":336},[320,1053,611],{"class":573},[320,1055,614],{"class":326},[320,1057,617],{"class":599},[320,1059,620],{"class":573},[320,1061,566],{"class":326},[320,1063,625],{"class":569},[320,1065,628],{"class":573},[320,1067,631],{"class":349},[320,1069,634],{"class":326},[320,1071,637],{"class":573},[320,1073,343],{"class":326},[320,1075,1076],{"class":573}," creds)",[320,1078,552],{"class":326},[320,1080,1081,1083,1085,1087,1089,1091,1093,1095,1097],{"class":322,"line":402},[320,1082,701],{"class":599},[320,1084,704],{"class":573},[320,1086,566],{"class":326},[320,1088,709],{"class":573},[320,1090,741],{"class":326},[320,1092,744],{"class":545},[320,1094,718],{"class":573},[320,1096,721],{"class":599},[320,1098,1099],{"class":326}," null;\n",[320,1101,1102,1104,1106,1109,1111,1113,1115,1117,1119,1121,1123,1126,1128,1130,1132,1134,1136,1138],{"class":322,"line":423},[320,1103,821],{"class":599},[320,1105,837],{"class":563},[320,1107,1108],{"class":573},"(id",[320,1110,343],{"class":326},[320,1112,873],{"class":573},[320,1114,566],{"class":326},[320,1116,855],{"class":573},[320,1118,858],{"class":349},[320,1120,663],{"class":573},[320,1122,634],{"class":326},[320,1124,1125],{"class":573}," email",[320,1127,343],{"class":326},[320,1129,873],{"class":573},[320,1131,566],{"class":326},[320,1133,855],{"class":573},[320,1135,660],{"class":349},[320,1137,983],{"class":573},[320,1139,552],{"class":326},[320,1141,1142,1144],{"class":322,"line":445},[320,1143,999],{"class":573},[320,1145,355],{"class":326},[320,1147,1148],{"class":322,"line":466},[320,1149,1007],{"class":573},[300,1151],{},[303,1153,1155],{"id":1154},"_3-initialize-at-startup","3. Initialize at startup",[529,1157,165],{"id":1158},"flutter",[311,1160,1163],{"className":535,"code":1161,"filename":1162,"language":538,"meta":316,"style":316},"import 'package:authyra_flutter/authyra_flutter.dart';\n\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n\n  await Authyra.initialize(\n    client: AuthyraClient(\n      providers: [myEmailProvider],\n      storage: SecureAuthStorage(),\n    ),\n  );\n\n  runApp(const MyApp());\n}\n","lib/main.dart",[282,1164,1165,1173,1177,1192,1207,1211,1226,1238,1250,1264,1270,1277,1281,1299],{"__ignoreMap":316},[320,1166,1167,1169,1171],{"class":322,"line":323},[320,1168,546],{"class":545},[320,1170,549],{"class":349},[320,1172,552],{"class":326},[320,1174,1175],{"class":322,"line":330},[320,1176,558],{"emptyLinePlaceholder":557},[320,1178,1179,1182,1185,1188,1190],{"class":322,"line":358},[320,1180,1181],{"class":336},"void",[320,1183,1184],{"class":569}," main",[320,1186,1187],{"class":573},"() ",[320,1189,600],{"class":599},[320,1191,603],{"class":573},[320,1193,1194,1197,1199,1202,1205],{"class":322,"line":380},[320,1195,1196],{"class":563},"  WidgetsFlutterBinding",[320,1198,566],{"class":326},[320,1200,1201],{"class":569},"ensureInitialized",[320,1203,1204],{"class":573},"()",[320,1206,552],{"class":326},[320,1208,1209],{"class":322,"line":402},[320,1210,558],{"emptyLinePlaceholder":557},[320,1212,1213,1216,1219,1221,1224],{"class":322,"line":423},[320,1214,1215],{"class":599},"  await",[320,1217,1218],{"class":563}," Authyra",[320,1220,566],{"class":326},[320,1222,1223],{"class":569},"initialize",[320,1225,574],{"class":573},[320,1227,1228,1231,1233,1236],{"class":322,"line":445},[320,1229,1230],{"class":573},"    client",[320,1232,343],{"class":326},[320,1234,1235],{"class":563}," AuthyraClient",[320,1237,574],{"class":573},[320,1239,1240,1243,1245,1248],{"class":322,"line":466},[320,1241,1242],{"class":573},"      providers",[320,1244,343],{"class":326},[320,1246,1247],{"class":573}," [myEmailProvider]",[320,1249,355],{"class":326},[320,1251,1252,1255,1257,1260,1262],{"class":322,"line":685},[320,1253,1254],{"class":573},"      storage",[320,1256,343],{"class":326},[320,1258,1259],{"class":563}," SecureAuthStorage",[320,1261,1204],{"class":573},[320,1263,355],{"class":326},[320,1265,1266,1268],{"class":322,"line":693},[320,1267,991],{"class":573},[320,1269,355],{"class":326},[320,1271,1272,1275],{"class":322,"line":698},[320,1273,1274],{"class":573},"  )",[320,1276,552],{"class":326},[320,1278,1279],{"class":322,"line":730},[320,1280,558],{"emptyLinePlaceholder":557},[320,1282,1283,1286,1288,1291,1294,1297],{"class":322,"line":750},[320,1284,1285],{"class":569},"  runApp",[320,1287,628],{"class":573},[320,1289,1290],{"class":336},"const",[320,1292,1293],{"class":563}," MyApp",[320,1295,1296],{"class":573},"())",[320,1298,552],{"class":326},[320,1300,1301],{"class":322,"line":761},[320,1302,469],{"class":573},[529,1304,1306],{"id":1305},"dart-backend","Dart backend",[311,1308,1311],{"className":535,"code":1309,"filename":1310,"language":538,"meta":316,"style":316},"import 'package:authyra/authyra.dart';\n\nfinal client = AuthyraClient(\n  providers: [myEmailProvider],\n  storage: MyRedisStorage(),\n);\n\nawait client.initialize();\n","bin/server.dart",[282,1312,1313,1322,1326,1340,1351,1365,1372,1376],{"__ignoreMap":316},[320,1314,1315,1317,1320],{"class":322,"line":323},[320,1316,546],{"class":545},[320,1318,1319],{"class":349}," 'package:authyra/authyra.dart'",[320,1321,552],{"class":326},[320,1323,1324],{"class":322,"line":330},[320,1325,558],{"emptyLinePlaceholder":557},[320,1327,1328,1331,1334,1336,1338],{"class":322,"line":358},[320,1329,1330],{"class":336},"final",[320,1332,1333],{"class":573}," client ",[320,1335,614],{"class":326},[320,1337,1235],{"class":563},[320,1339,574],{"class":573},[320,1341,1342,1345,1347,1349],{"class":322,"line":380},[320,1343,1344],{"class":573},"  providers",[320,1346,343],{"class":326},[320,1348,1247],{"class":573},[320,1350,355],{"class":326},[320,1352,1353,1356,1358,1361,1363],{"class":322,"line":402},[320,1354,1355],{"class":573},"  storage",[320,1357,343],{"class":326},[320,1359,1360],{"class":563}," MyRedisStorage",[320,1362,1204],{"class":573},[320,1364,355],{"class":326},[320,1366,1367,1370],{"class":322,"line":423},[320,1368,1369],{"class":573},")",[320,1371,552],{"class":326},[320,1373,1374],{"class":322,"line":445},[320,1375,558],{"emptyLinePlaceholder":557},[320,1377,1378,1381,1384,1386,1388,1390],{"class":322,"line":466},[320,1379,1380],{"class":599},"await",[320,1382,1383],{"class":573}," client",[320,1385,566],{"class":326},[320,1387,1223],{"class":569},[320,1389,1204],{"class":573},[320,1391,552],{"class":326},[300,1393],{},[303,1395,1397],{"id":1396},"_4-build-the-sign-in-form","4. Build the sign-in form",[311,1399,1402],{"className":535,"code":1400,"filename":1401,"language":538,"meta":316,"style":316},"import 'package:authyra_flutter/authyra_flutter.dart';\nimport 'package:flutter/material.dart';\n\nclass LoginPage extends StatefulWidget {\n  const LoginPage({super.key});\n\n  @override\n  State\u003CLoginPage> createState() => _LoginPageState();\n}\n\nclass _LoginPageState extends State\u003CLoginPage> {\n  final _email    = TextEditingController();\n  final _password = TextEditingController();\n  bool _loading   = false;\n  String? _error;\n\n  Future\u003Cvoid> _signIn() async {\n    setState(() { _loading = true; _error = null; });\n    try {\n      await Authyra.instance.signIn('email', params: {\n        'email':    _email.text.trim(),\n        'password': _password.text,\n      });\n      // authStateChanges emits — your router navigates automatically\n    } on AuthenticationFailedException {\n      setState(() => _error = 'Invalid email or password.');\n    } catch (e) {\n      setState(() => _error = 'Something went wrong. Try again.');\n    } finally {\n      setState(() => _loading = false);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: Padding(\n        padding: const EdgeInsets.all(24),\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: [\n            TextField(\n              controller: _email,\n              decoration: const InputDecoration(labelText: 'Email'),\n              keyboardType: TextInputType.emailAddress,\n            ),\n            const SizedBox(height: 12),\n            TextField(\n              controller: _password,\n              decoration: const InputDecoration(labelText: 'Password'),\n              obscureText: true,\n            ),\n            if (_error != null) ...[\n              const SizedBox(height: 12),\n              Text(_error!, style: const TextStyle(color: Colors.red)),\n            ],\n            const SizedBox(height: 24),\n            FilledButton(\n              onPressed: _loading ? null : _signIn,\n              child: _loading\n                  ? const CircularProgressIndicator()\n                  : const Text('Sign in'),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n","lib/pages/login_page.dart",[282,1403,1404,1412,1421,1425,1441,1458,1462,1467,1496,1500,1504,1522,1539,1554,1567,1580,1584,1604,1629,1636,1666,1690,1706,1713,1718,1730,1751,1761,1780,1789,1809,1814,1820,1825,1830,1847,1857,1870,1898,1911,1929,1940,1948,1961,1986,2004,2012,2033,2040,2051,2073,2084,2091,2113,2131,2168,2176,2194,2202,2224,2235,2249,2269,2276,2284,2292,2299,2306,2311],{"__ignoreMap":316},[320,1405,1406,1408,1410],{"class":322,"line":323},[320,1407,546],{"class":545},[320,1409,549],{"class":349},[320,1411,552],{"class":326},[320,1413,1414,1416,1419],{"class":322,"line":330},[320,1415,546],{"class":545},[320,1417,1418],{"class":349}," 'package:flutter/material.dart'",[320,1420,552],{"class":326},[320,1422,1423],{"class":322,"line":358},[320,1424,558],{"emptyLinePlaceholder":557},[320,1426,1427,1430,1433,1436,1439],{"class":322,"line":380},[320,1428,1429],{"class":326},"class",[320,1431,1432],{"class":563}," LoginPage",[320,1434,1435],{"class":326}," extends",[320,1437,1438],{"class":563}," StatefulWidget",[320,1440,603],{"class":573},[320,1442,1443,1446,1448,1451,1453,1456],{"class":322,"line":402},[320,1444,1445],{"class":336},"  const",[320,1447,1432],{"class":563},[320,1449,1450],{"class":573},"({super",[320,1452,566],{"class":326},[320,1454,1455],{"class":573},"key})",[320,1457,552],{"class":326},[320,1459,1460],{"class":322,"line":423},[320,1461,558],{"emptyLinePlaceholder":557},[320,1463,1464],{"class":322,"line":445},[320,1465,1466],{"class":336},"  @override\n",[320,1468,1469,1472,1475,1478,1481,1484,1486,1489,1492,1494],{"class":322,"line":466},[320,1470,1471],{"class":563},"  State",[320,1473,1474],{"class":573},"\u003C",[320,1476,1477],{"class":563},"LoginPage",[320,1479,1480],{"class":573},"> ",[320,1482,1483],{"class":569},"createState",[320,1485,1187],{"class":573},[320,1487,1488],{"class":326},"=>",[320,1490,1491],{"class":563}," _LoginPageState",[320,1493,1204],{"class":573},[320,1495,552],{"class":326},[320,1497,1498],{"class":322,"line":685},[320,1499,469],{"class":573},[320,1501,1502],{"class":322,"line":693},[320,1503,558],{"emptyLinePlaceholder":557},[320,1505,1506,1508,1510,1512,1515,1517,1519],{"class":322,"line":698},[320,1507,1429],{"class":326},[320,1509,1491],{"class":563},[320,1511,1435],{"class":326},[320,1513,1514],{"class":563}," State",[320,1516,1474],{"class":573},[320,1518,1477],{"class":563},[320,1520,1521],{"class":573},"> {\n",[320,1523,1524,1527,1530,1532,1535,1537],{"class":322,"line":730},[320,1525,1526],{"class":336},"  final",[320,1528,1529],{"class":573}," _email    ",[320,1531,614],{"class":326},[320,1533,1534],{"class":563}," TextEditingController",[320,1536,1204],{"class":573},[320,1538,552],{"class":326},[320,1540,1541,1543,1546,1548,1550,1552],{"class":322,"line":750},[320,1542,1526],{"class":336},[320,1544,1545],{"class":573}," _password ",[320,1547,614],{"class":326},[320,1549,1534],{"class":563},[320,1551,1204],{"class":573},[320,1553,552],{"class":326},[320,1555,1556,1559,1562,1564],{"class":322,"line":761},[320,1557,1558],{"class":563},"  bool",[320,1560,1561],{"class":573}," _loading   ",[320,1563,614],{"class":326},[320,1565,1566],{"class":326}," false;\n",[320,1568,1569,1572,1575,1578],{"class":322,"line":787},[320,1570,1571],{"class":563},"  String",[320,1573,1574],{"class":326},"?",[320,1576,1577],{"class":573}," _error",[320,1579,552],{"class":326},[320,1581,1582],{"class":322,"line":799},[320,1583,558],{"emptyLinePlaceholder":557},[320,1585,1586,1589,1591,1593,1595,1598,1600,1602],{"class":322,"line":807},[320,1587,1588],{"class":563},"  Future",[320,1590,1474],{"class":573},[320,1592,1181],{"class":336},[320,1594,1480],{"class":573},[320,1596,1597],{"class":569},"_signIn",[320,1599,1187],{"class":573},[320,1601,600],{"class":599},[320,1603,603],{"class":573},[320,1605,1606,1609,1612,1614,1617,1620,1622,1624,1627],{"class":322,"line":813},[320,1607,1608],{"class":569},"    setState",[320,1610,1611],{"class":573},"(() { _loading ",[320,1613,614],{"class":326},[320,1615,1616],{"class":326}," true;",[320,1618,1619],{"class":573}," _error ",[320,1621,614],{"class":326},[320,1623,724],{"class":326},[320,1625,1626],{"class":573}," })",[320,1628,552],{"class":326},[320,1630,1631,1634],{"class":322,"line":818},[320,1632,1633],{"class":599},"    try",[320,1635,603],{"class":573},[320,1637,1638,1641,1643,1645,1648,1650,1653,1655,1657,1659,1662,1664],{"class":322,"line":829},[320,1639,1640],{"class":599},"      await",[320,1642,1218],{"class":563},[320,1644,566],{"class":326},[320,1646,1647],{"class":573},"instance",[320,1649,566],{"class":326},[320,1651,1652],{"class":569},"signIn",[320,1654,628],{"class":573},[320,1656,660],{"class":349},[320,1658,634],{"class":326},[320,1660,1661],{"class":573}," params",[320,1663,343],{"class":326},[320,1665,603],{"class":573},[320,1667,1668,1671,1673,1676,1678,1681,1683,1686,1688],{"class":322,"line":842},[320,1669,1670],{"class":349},"        'email'",[320,1672,343],{"class":326},[320,1674,1675],{"class":573},"    _email",[320,1677,566],{"class":326},[320,1679,1680],{"class":573},"text",[320,1682,566],{"class":326},[320,1684,1685],{"class":569},"trim",[320,1687,1204],{"class":573},[320,1689,355],{"class":326},[320,1691,1692,1695,1697,1700,1702,1704],{"class":322,"line":865},[320,1693,1694],{"class":349},"        'password'",[320,1696,343],{"class":326},[320,1698,1699],{"class":573}," _password",[320,1701,566],{"class":326},[320,1703,1680],{"class":573},[320,1705,355],{"class":326},[320,1707,1708,1711],{"class":322,"line":886},[320,1709,1710],{"class":573},"      })",[320,1712,552],{"class":326},[320,1714,1715],{"class":322,"line":908},[320,1716,1717],{"class":515},"      // authStateChanges emits — your router navigates automatically\n",[320,1719,1720,1723,1726,1728],{"class":322,"line":915},[320,1721,1722],{"class":573},"    } ",[320,1724,1725],{"class":599},"on",[320,1727,756],{"class":563},[320,1729,603],{"class":573},[320,1731,1732,1735,1738,1740,1742,1744,1747,1749],{"class":322,"line":936},[320,1733,1734],{"class":569},"      setState",[320,1736,1737],{"class":573},"(() ",[320,1739,1488],{"class":326},[320,1741,1619],{"class":573},[320,1743,614],{"class":326},[320,1745,1746],{"class":349}," 'Invalid email or password.'",[320,1748,1369],{"class":573},[320,1750,552],{"class":326},[320,1752,1753,1755,1758],{"class":322,"line":957},[320,1754,1722],{"class":573},[320,1756,1757],{"class":599},"catch",[320,1759,1760],{"class":573}," (e) {\n",[320,1762,1763,1765,1767,1769,1771,1773,1776,1778],{"class":322,"line":988},[320,1764,1734],{"class":569},[320,1766,1737],{"class":573},[320,1768,1488],{"class":326},[320,1770,1619],{"class":573},[320,1772,614],{"class":326},[320,1774,1775],{"class":349}," 'Something went wrong. Try again.'",[320,1777,1369],{"class":573},[320,1779,552],{"class":326},[320,1781,1782,1784,1787],{"class":322,"line":996},[320,1783,1722],{"class":573},[320,1785,1786],{"class":599},"finally",[320,1788,603],{"class":573},[320,1790,1791,1793,1795,1797,1800,1802,1805,1807],{"class":322,"line":1004},[320,1792,1734],{"class":569},[320,1794,1737],{"class":573},[320,1796,1488],{"class":326},[320,1798,1799],{"class":573}," _loading ",[320,1801,614],{"class":326},[320,1803,1804],{"class":326}," false",[320,1806,1369],{"class":573},[320,1808,552],{"class":326},[320,1810,1812],{"class":322,"line":1811},31,[320,1813,810],{"class":573},[320,1815,1817],{"class":322,"line":1816},32,[320,1818,1819],{"class":573},"  }\n",[320,1821,1823],{"class":322,"line":1822},33,[320,1824,558],{"emptyLinePlaceholder":557},[320,1826,1828],{"class":322,"line":1827},34,[320,1829,1466],{"class":336},[320,1831,1833,1836,1839,1841,1844],{"class":322,"line":1832},35,[320,1834,1835],{"class":563},"  Widget",[320,1837,1838],{"class":569}," build",[320,1840,628],{"class":573},[320,1842,1843],{"class":563},"BuildContext",[320,1845,1846],{"class":573}," context) {\n",[320,1848,1850,1852,1855],{"class":322,"line":1849},36,[320,1851,821],{"class":599},[320,1853,1854],{"class":563}," Scaffold",[320,1856,574],{"class":573},[320,1858,1860,1863,1865,1868],{"class":322,"line":1859},37,[320,1861,1862],{"class":573},"      body",[320,1864,343],{"class":326},[320,1866,1867],{"class":563}," Padding",[320,1869,574],{"class":573},[320,1871,1873,1876,1878,1881,1884,1886,1889,1891,1894,1896],{"class":322,"line":1872},38,[320,1874,1875],{"class":573},"        padding",[320,1877,343],{"class":326},[320,1879,1880],{"class":336}," const",[320,1882,1883],{"class":563}," EdgeInsets",[320,1885,566],{"class":326},[320,1887,1888],{"class":569},"all",[320,1890,628],{"class":573},[320,1892,1893],{"class":545},"24",[320,1895,1369],{"class":573},[320,1897,355],{"class":326},[320,1899,1901,1904,1906,1909],{"class":322,"line":1900},39,[320,1902,1903],{"class":573},"        child",[320,1905,343],{"class":326},[320,1907,1908],{"class":563}," Column",[320,1910,574],{"class":573},[320,1912,1914,1917,1919,1922,1924,1927],{"class":322,"line":1913},40,[320,1915,1916],{"class":573},"          mainAxisAlignment",[320,1918,343],{"class":326},[320,1920,1921],{"class":563}," MainAxisAlignment",[320,1923,566],{"class":326},[320,1925,1926],{"class":573},"center",[320,1928,355],{"class":326},[320,1930,1932,1935,1937],{"class":322,"line":1931},41,[320,1933,1934],{"class":573},"          children",[320,1936,343],{"class":326},[320,1938,1939],{"class":573}," [\n",[320,1941,1943,1946],{"class":322,"line":1942},42,[320,1944,1945],{"class":563},"            TextField",[320,1947,574],{"class":573},[320,1949,1951,1954,1956,1959],{"class":322,"line":1950},43,[320,1952,1953],{"class":573},"              controller",[320,1955,343],{"class":326},[320,1957,1958],{"class":573}," _email",[320,1960,355],{"class":326},[320,1962,1964,1967,1969,1971,1974,1977,1979,1982,1984],{"class":322,"line":1963},44,[320,1965,1966],{"class":573},"              decoration",[320,1968,343],{"class":326},[320,1970,1880],{"class":336},[320,1972,1973],{"class":563}," InputDecoration",[320,1975,1976],{"class":573},"(labelText",[320,1978,343],{"class":326},[320,1980,1981],{"class":349}," 'Email'",[320,1983,1369],{"class":573},[320,1985,355],{"class":326},[320,1987,1989,1992,1994,1997,1999,2002],{"class":322,"line":1988},45,[320,1990,1991],{"class":573},"              keyboardType",[320,1993,343],{"class":326},[320,1995,1996],{"class":563}," TextInputType",[320,1998,566],{"class":326},[320,2000,2001],{"class":573},"emailAddress",[320,2003,355],{"class":326},[320,2005,2007,2010],{"class":322,"line":2006},46,[320,2008,2009],{"class":573},"            )",[320,2011,355],{"class":326},[320,2013,2015,2018,2021,2024,2026,2029,2031],{"class":322,"line":2014},47,[320,2016,2017],{"class":336},"            const",[320,2019,2020],{"class":563}," SizedBox",[320,2022,2023],{"class":573},"(height",[320,2025,343],{"class":326},[320,2027,2028],{"class":545}," 12",[320,2030,1369],{"class":573},[320,2032,355],{"class":326},[320,2034,2036,2038],{"class":322,"line":2035},48,[320,2037,1945],{"class":563},[320,2039,574],{"class":573},[320,2041,2043,2045,2047,2049],{"class":322,"line":2042},49,[320,2044,1953],{"class":573},[320,2046,343],{"class":326},[320,2048,1699],{"class":573},[320,2050,355],{"class":326},[320,2052,2054,2056,2058,2060,2062,2064,2066,2069,2071],{"class":322,"line":2053},50,[320,2055,1966],{"class":573},[320,2057,343],{"class":326},[320,2059,1880],{"class":336},[320,2061,1973],{"class":563},[320,2063,1976],{"class":573},[320,2065,343],{"class":326},[320,2067,2068],{"class":349}," 'Password'",[320,2070,1369],{"class":573},[320,2072,355],{"class":326},[320,2074,2076,2079,2081],{"class":322,"line":2075},51,[320,2077,2078],{"class":573},"              obscureText",[320,2080,343],{"class":326},[320,2082,2083],{"class":326}," true,\n",[320,2085,2087,2089],{"class":322,"line":2086},52,[320,2088,2009],{"class":573},[320,2090,355],{"class":326},[320,2092,2094,2097,2100,2102,2105,2107,2110],{"class":322,"line":2093},53,[320,2095,2096],{"class":599},"            if",[320,2098,2099],{"class":573}," (_error ",[320,2101,741],{"class":326},[320,2103,2104],{"class":326}," null",[320,2106,718],{"class":573},[320,2108,2109],{"class":326},"...",[320,2111,2112],{"class":573},"[\n",[320,2114,2116,2119,2121,2123,2125,2127,2129],{"class":322,"line":2115},54,[320,2117,2118],{"class":336},"              const",[320,2120,2020],{"class":563},[320,2122,2023],{"class":573},[320,2124,343],{"class":326},[320,2126,2028],{"class":545},[320,2128,1369],{"class":573},[320,2130,355],{"class":326},[320,2132,2134,2137,2140,2143,2146,2148,2150,2153,2156,2158,2161,2163,2166],{"class":322,"line":2133},55,[320,2135,2136],{"class":563},"              Text",[320,2138,2139],{"class":573},"(_error",[320,2141,2142],{"class":326},"!,",[320,2144,2145],{"class":573}," style",[320,2147,343],{"class":326},[320,2149,1880],{"class":336},[320,2151,2152],{"class":563}," TextStyle",[320,2154,2155],{"class":573},"(color",[320,2157,343],{"class":326},[320,2159,2160],{"class":563}," Colors",[320,2162,566],{"class":326},[320,2164,2165],{"class":573},"red))",[320,2167,355],{"class":326},[320,2169,2171,2174],{"class":322,"line":2170},56,[320,2172,2173],{"class":573},"            ]",[320,2175,355],{"class":326},[320,2177,2179,2181,2183,2185,2187,2190,2192],{"class":322,"line":2178},57,[320,2180,2017],{"class":336},[320,2182,2020],{"class":563},[320,2184,2023],{"class":573},[320,2186,343],{"class":326},[320,2188,2189],{"class":545}," 24",[320,2191,1369],{"class":573},[320,2193,355],{"class":326},[320,2195,2197,2200],{"class":322,"line":2196},58,[320,2198,2199],{"class":563},"            FilledButton",[320,2201,574],{"class":573},[320,2203,2205,2208,2210,2212,2214,2216,2219,2222],{"class":322,"line":2204},59,[320,2206,2207],{"class":573},"              onPressed",[320,2209,343],{"class":326},[320,2211,1799],{"class":573},[320,2213,1574],{"class":326},[320,2215,2104],{"class":326},[320,2217,2218],{"class":326}," :",[320,2220,2221],{"class":573}," _signIn",[320,2223,355],{"class":326},[320,2225,2227,2230,2232],{"class":322,"line":2226},60,[320,2228,2229],{"class":573},"              child",[320,2231,343],{"class":326},[320,2233,2234],{"class":573}," _loading\n",[320,2236,2238,2241,2243,2246],{"class":322,"line":2237},61,[320,2239,2240],{"class":326},"                  ?",[320,2242,1880],{"class":336},[320,2244,2245],{"class":563}," CircularProgressIndicator",[320,2247,2248],{"class":573},"()\n",[320,2250,2252,2255,2257,2260,2262,2265,2267],{"class":322,"line":2251},62,[320,2253,2254],{"class":326},"                  :",[320,2256,1880],{"class":336},[320,2258,2259],{"class":563}," Text",[320,2261,628],{"class":573},[320,2263,2264],{"class":349},"'Sign in'",[320,2266,1369],{"class":573},[320,2268,355],{"class":326},[320,2270,2272,2274],{"class":322,"line":2271},63,[320,2273,2009],{"class":573},[320,2275,355],{"class":326},[320,2277,2279,2282],{"class":322,"line":2278},64,[320,2280,2281],{"class":573},"          ]",[320,2283,355],{"class":326},[320,2285,2287,2290],{"class":322,"line":2286},65,[320,2288,2289],{"class":573},"        )",[320,2291,355],{"class":326},[320,2293,2295,2297],{"class":322,"line":2294},66,[320,2296,802],{"class":573},[320,2298,355],{"class":326},[320,2300,2302,2304],{"class":322,"line":2301},67,[320,2303,991],{"class":573},[320,2305,552],{"class":326},[320,2307,2309],{"class":322,"line":2308},68,[320,2310,1819],{"class":573},[320,2312,2314],{"class":322,"line":2313},69,[320,2315,469],{"class":573},[300,2317],{},[303,2319,2321],{"id":2320},"_5-react-to-auth-state","5. React to auth state",[529,2323,294],{"id":2324},"streambuilder",[311,2326,2329],{"className":535,"code":2327,"filename":2328,"language":538,"meta":316,"style":316},"import 'package:authyra_flutter/authyra_flutter.dart';\nimport 'package:flutter/material.dart';\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: StreamBuilder\u003CAuthState>(\n        stream: Authyra.instance.authStateChanges,\n        builder: (context, snapshot) {\n          final state = snapshot.data ?? AuthState.unauthenticated();\n          return switch (state.type) {\n            AuthStateType.authenticated   => HomePage(user: state.user!),\n            AuthStateType.unauthenticated => const LoginPage(),\n            AuthStateType.error           => ErrorPage(state.error!),\n          };\n        },\n      ),\n    );\n  }\n}\n","lib/app.dart",[282,2330,2331,2339,2347,2351,2364,2378,2382,2386,2398,2407,2424,2444,2459,2492,2508,2542,2561,2589,2596,2603,2609,2615,2619],{"__ignoreMap":316},[320,2332,2333,2335,2337],{"class":322,"line":323},[320,2334,546],{"class":545},[320,2336,549],{"class":349},[320,2338,552],{"class":326},[320,2340,2341,2343,2345],{"class":322,"line":330},[320,2342,546],{"class":545},[320,2344,1418],{"class":349},[320,2346,552],{"class":326},[320,2348,2349],{"class":322,"line":358},[320,2350,558],{"emptyLinePlaceholder":557},[320,2352,2353,2355,2357,2359,2362],{"class":322,"line":380},[320,2354,1429],{"class":326},[320,2356,1293],{"class":563},[320,2358,1435],{"class":326},[320,2360,2361],{"class":563}," StatelessWidget",[320,2363,603],{"class":573},[320,2365,2366,2368,2370,2372,2374,2376],{"class":322,"line":402},[320,2367,1445],{"class":336},[320,2369,1293],{"class":563},[320,2371,1450],{"class":573},[320,2373,566],{"class":326},[320,2375,1455],{"class":573},[320,2377,552],{"class":326},[320,2379,2380],{"class":322,"line":423},[320,2381,558],{"emptyLinePlaceholder":557},[320,2383,2384],{"class":322,"line":445},[320,2385,1466],{"class":336},[320,2387,2388,2390,2392,2394,2396],{"class":322,"line":466},[320,2389,1835],{"class":563},[320,2391,1838],{"class":569},[320,2393,628],{"class":573},[320,2395,1843],{"class":563},[320,2397,1846],{"class":573},[320,2399,2400,2402,2405],{"class":322,"line":685},[320,2401,821],{"class":599},[320,2403,2404],{"class":563}," MaterialApp",[320,2406,574],{"class":573},[320,2408,2409,2412,2414,2417,2419,2421],{"class":322,"line":693},[320,2410,2411],{"class":573},"      home",[320,2413,343],{"class":326},[320,2415,2416],{"class":563}," StreamBuilder",[320,2418,1474],{"class":573},[320,2420,226],{"class":563},[320,2422,2423],{"class":573},">(\n",[320,2425,2426,2429,2431,2433,2435,2437,2439,2442],{"class":322,"line":698},[320,2427,2428],{"class":573},"        stream",[320,2430,343],{"class":326},[320,2432,1218],{"class":563},[320,2434,566],{"class":326},[320,2436,1647],{"class":573},[320,2438,566],{"class":326},[320,2440,2441],{"class":573},"authStateChanges",[320,2443,355],{"class":326},[320,2445,2446,2449,2451,2454,2456],{"class":322,"line":730},[320,2447,2448],{"class":573},"        builder",[320,2450,343],{"class":326},[320,2452,2453],{"class":573}," (context",[320,2455,634],{"class":326},[320,2457,2458],{"class":573}," snapshot) {\n",[320,2460,2461,2464,2467,2469,2472,2474,2477,2480,2483,2485,2488,2490],{"class":322,"line":750},[320,2462,2463],{"class":336},"          final",[320,2465,2466],{"class":573}," state ",[320,2468,614],{"class":326},[320,2470,2471],{"class":573}," snapshot",[320,2473,566],{"class":326},[320,2475,2476],{"class":573},"data ",[320,2478,2479],{"class":326},"??",[320,2481,2482],{"class":563}," AuthState",[320,2484,566],{"class":326},[320,2486,2487],{"class":569},"unauthenticated",[320,2489,1204],{"class":573},[320,2491,552],{"class":326},[320,2493,2494,2497,2500,2503,2505],{"class":322,"line":761},[320,2495,2496],{"class":599},"          return",[320,2498,2499],{"class":599}," switch",[320,2501,2502],{"class":573}," (state",[320,2504,566],{"class":326},[320,2506,2507],{"class":573},"type) {\n",[320,2509,2510,2513,2515,2518,2520,2523,2526,2528,2531,2533,2536,2538,2540],{"class":322,"line":787},[320,2511,2512],{"class":563},"            AuthStateType",[320,2514,566],{"class":326},[320,2516,2517],{"class":573},"authenticated   ",[320,2519,1488],{"class":326},[320,2521,2522],{"class":563}," HomePage",[320,2524,2525],{"class":573},"(user",[320,2527,343],{"class":326},[320,2529,2530],{"class":573}," state",[320,2532,566],{"class":326},[320,2534,2535],{"class":573},"user",[320,2537,654],{"class":326},[320,2539,1369],{"class":573},[320,2541,355],{"class":326},[320,2543,2544,2546,2548,2551,2553,2555,2557,2559],{"class":322,"line":799},[320,2545,2512],{"class":563},[320,2547,566],{"class":326},[320,2549,2550],{"class":573},"unauthenticated ",[320,2552,1488],{"class":326},[320,2554,1880],{"class":336},[320,2556,1432],{"class":563},[320,2558,1204],{"class":573},[320,2560,355],{"class":326},[320,2562,2563,2565,2567,2570,2572,2575,2578,2580,2583,2585,2587],{"class":322,"line":807},[320,2564,2512],{"class":563},[320,2566,566],{"class":326},[320,2568,2569],{"class":573},"error           ",[320,2571,1488],{"class":326},[320,2573,2574],{"class":563}," ErrorPage",[320,2576,2577],{"class":573},"(state",[320,2579,566],{"class":326},[320,2581,2582],{"class":573},"error",[320,2584,654],{"class":326},[320,2586,1369],{"class":573},[320,2588,355],{"class":326},[320,2590,2591,2594],{"class":322,"line":813},[320,2592,2593],{"class":573},"          }",[320,2595,552],{"class":326},[320,2597,2598,2601],{"class":322,"line":818},[320,2599,2600],{"class":573},"        }",[320,2602,355],{"class":326},[320,2604,2605,2607],{"class":322,"line":829},[320,2606,802],{"class":573},[320,2608,355],{"class":326},[320,2610,2611,2613],{"class":322,"line":842},[320,2612,991],{"class":573},[320,2614,552],{"class":326},[320,2616,2617],{"class":322,"line":865},[320,2618,1819],{"class":573},[320,2620,2621],{"class":322,"line":886},[320,2622,469],{"class":573},[529,2624,2626],{"id":2625},"gorouter","GoRouter",[311,2628,2630],{"className":535,"code":2629,"language":538,"meta":316,"style":316},"GoRouter(\n  refreshListenable: StreamToListenable(Authyra.instance.authStateChanges),\n  redirect: (context, routerState) {\n    final authenticated = Authyra.instance.isAuthenticated;\n    final goingToLogin  = routerState.uri.path == '/login';\n\n    if (!authenticated && !goingToLogin) return '/login';\n    if (authenticated  &&  goingToLogin) return '/home';\n    return null;\n  },\n  routes: [\n    GoRoute(path: '/login', builder: (_, __) => const LoginPage()),\n    GoRoute(path: '/home',  builder: (_, __) => const HomePage()),\n  ],\n);\n",[282,2631,2632,2638,2664,2678,2700,2729,2733,2760,2779,2785,2791,2800,2837,2870,2877],{"__ignoreMap":316},[320,2633,2634,2636],{"class":322,"line":323},[320,2635,2626],{"class":563},[320,2637,574],{"class":573},[320,2639,2640,2643,2645,2648,2650,2653,2655,2657,2659,2662],{"class":322,"line":330},[320,2641,2642],{"class":573},"  refreshListenable",[320,2644,343],{"class":326},[320,2646,2647],{"class":563}," StreamToListenable",[320,2649,628],{"class":573},[320,2651,2652],{"class":563},"Authyra",[320,2654,566],{"class":326},[320,2656,1647],{"class":573},[320,2658,566],{"class":326},[320,2660,2661],{"class":573},"authStateChanges)",[320,2663,355],{"class":326},[320,2665,2666,2669,2671,2673,2675],{"class":322,"line":358},[320,2667,2668],{"class":573},"  redirect",[320,2670,343],{"class":326},[320,2672,2453],{"class":573},[320,2674,634],{"class":326},[320,2676,2677],{"class":573}," routerState) {\n",[320,2679,2680,2682,2685,2687,2689,2691,2693,2695,2698],{"class":322,"line":380},[320,2681,608],{"class":336},[320,2683,2684],{"class":573}," authenticated ",[320,2686,614],{"class":326},[320,2688,1218],{"class":563},[320,2690,566],{"class":326},[320,2692,1647],{"class":573},[320,2694,566],{"class":326},[320,2696,2697],{"class":573},"isAuthenticated",[320,2699,552],{"class":326},[320,2701,2702,2704,2707,2709,2712,2714,2717,2719,2722,2724,2727],{"class":322,"line":402},[320,2703,608],{"class":336},[320,2705,2706],{"class":573}," goingToLogin  ",[320,2708,614],{"class":326},[320,2710,2711],{"class":573}," routerState",[320,2713,566],{"class":326},[320,2715,2716],{"class":573},"uri",[320,2718,566],{"class":326},[320,2720,2721],{"class":573},"path ",[320,2723,712],{"class":326},[320,2725,2726],{"class":349}," '/login'",[320,2728,552],{"class":326},[320,2730,2731],{"class":322,"line":423},[320,2732,558],{"emptyLinePlaceholder":557},[320,2734,2735,2737,2740,2742,2745,2748,2751,2754,2756,2758],{"class":322,"line":445},[320,2736,701],{"class":599},[320,2738,2739],{"class":573}," (",[320,2741,654],{"class":326},[320,2743,2744],{"class":573},"authenticated ",[320,2746,2747],{"class":326},"&&",[320,2749,2750],{"class":326}," !",[320,2752,2753],{"class":573},"goingToLogin) ",[320,2755,721],{"class":599},[320,2757,2726],{"class":349},[320,2759,552],{"class":326},[320,2761,2762,2764,2767,2769,2772,2774,2777],{"class":322,"line":466},[320,2763,701],{"class":599},[320,2765,2766],{"class":573}," (authenticated  ",[320,2768,2747],{"class":326},[320,2770,2771],{"class":573},"  goingToLogin) ",[320,2773,721],{"class":599},[320,2775,2776],{"class":349}," '/home'",[320,2778,552],{"class":326},[320,2780,2781,2783],{"class":322,"line":685},[320,2782,821],{"class":599},[320,2784,1099],{"class":326},[320,2786,2787,2789],{"class":322,"line":693},[320,2788,999],{"class":573},[320,2790,355],{"class":326},[320,2792,2793,2796,2798],{"class":322,"line":698},[320,2794,2795],{"class":573},"  routes",[320,2797,343],{"class":326},[320,2799,1939],{"class":573},[320,2801,2802,2805,2808,2810,2812,2814,2817,2819,2822,2824,2827,2829,2831,2833,2835],{"class":322,"line":730},[320,2803,2804],{"class":563},"    GoRoute",[320,2806,2807],{"class":573},"(path",[320,2809,343],{"class":326},[320,2811,2726],{"class":349},[320,2813,634],{"class":326},[320,2815,2816],{"class":573}," builder",[320,2818,343],{"class":326},[320,2820,2821],{"class":573}," (_",[320,2823,634],{"class":326},[320,2825,2826],{"class":573}," __) ",[320,2828,1488],{"class":326},[320,2830,1880],{"class":336},[320,2832,1432],{"class":563},[320,2834,1296],{"class":573},[320,2836,355],{"class":326},[320,2838,2839,2841,2843,2845,2847,2849,2852,2854,2856,2858,2860,2862,2864,2866,2868],{"class":322,"line":750},[320,2840,2804],{"class":563},[320,2842,2807],{"class":573},[320,2844,343],{"class":326},[320,2846,2776],{"class":349},[320,2848,634],{"class":326},[320,2850,2851],{"class":573},"  builder",[320,2853,343],{"class":326},[320,2855,2821],{"class":573},[320,2857,634],{"class":326},[320,2859,2826],{"class":573},[320,2861,1488],{"class":326},[320,2863,1880],{"class":336},[320,2865,2522],{"class":563},[320,2867,1296],{"class":573},[320,2869,355],{"class":326},[320,2871,2872,2875],{"class":322,"line":761},[320,2873,2874],{"class":573},"  ]",[320,2876,355],{"class":326},[320,2878,2879,2881],{"class":322,"line":787},[320,2880,1369],{"class":573},[320,2882,552],{"class":326},[300,2884],{},[303,2886,2888],{"id":2887},"_6-access-the-token-for-api-calls","6. Access the token for API calls",[311,2890,2892],{"className":535,"code":2891,"language":538,"meta":316,"style":316},"final token = await Authyra.instance.getAccessToken();\nmyHttpClient.options.headers['Authorization'] = 'Bearer $token';\n",[282,2893,2894,2920],{"__ignoreMap":316},[320,2895,2896,2898,2901,2903,2905,2907,2909,2911,2913,2916,2918],{"class":322,"line":323},[320,2897,1330],{"class":336},[320,2899,2900],{"class":573}," token ",[320,2902,614],{"class":326},[320,2904,617],{"class":599},[320,2906,1218],{"class":563},[320,2908,566],{"class":326},[320,2910,1647],{"class":573},[320,2912,566],{"class":326},[320,2914,2915],{"class":569},"getAccessToken",[320,2917,1204],{"class":573},[320,2919,552],{"class":326},[320,2921,2922,2925,2927,2930,2932,2935,2938,2941,2943,2946,2949,2952,2954],{"class":322,"line":330},[320,2923,2924],{"class":573},"myHttpClient",[320,2926,566],{"class":326},[320,2928,2929],{"class":573},"options",[320,2931,566],{"class":326},[320,2933,2934],{"class":573},"headers[",[320,2936,2937],{"class":349},"'Authorization'",[320,2939,2940],{"class":573},"] ",[320,2942,614],{"class":326},[320,2944,2945],{"class":349}," 'Bearer ",[320,2947,2948],{"class":573},"$",[320,2950,2951],{"class":770},"token",[320,2953,782],{"class":349},[320,2955,552],{"class":326},[271,2957,2958],{},"Or read it from the full session:",[311,2960,2962],{"className":535,"code":2961,"language":538,"meta":316,"style":316},"final session = await Authyra.instance.getSession();\nprint('Token expires: ${session?.expiresAt}');\nprint('User: ${session?.user.email}');\n",[282,2963,2964,2990,3018],{"__ignoreMap":316},[320,2965,2966,2968,2971,2973,2975,2977,2979,2981,2983,2986,2988],{"class":322,"line":323},[320,2967,1330],{"class":336},[320,2969,2970],{"class":573}," session ",[320,2972,614],{"class":326},[320,2974,617],{"class":599},[320,2976,1218],{"class":563},[320,2978,566],{"class":326},[320,2980,1647],{"class":573},[320,2982,566],{"class":326},[320,2984,2985],{"class":569},"getSession",[320,2987,1204],{"class":573},[320,2989,552],{"class":326},[320,2991,2992,2995,2997,3000,3002,3005,3008,3010,3012,3014,3016],{"class":322,"line":330},[320,2993,2994],{"class":569},"print",[320,2996,628],{"class":573},[320,2998,2999],{"class":349},"'Token expires: ",[320,3001,767],{"class":573},[320,3003,3004],{"class":770},"session",[320,3006,3007],{"class":573},"?.",[320,3009,450],{"class":770},[320,3011,779],{"class":573},[320,3013,782],{"class":349},[320,3015,1369],{"class":573},[320,3017,552],{"class":326},[320,3019,3020,3022,3024,3027,3029,3031,3033,3035,3037,3039,3041,3043,3045],{"class":322,"line":358},[320,3021,2994],{"class":569},[320,3023,628],{"class":573},[320,3025,3026],{"class":349},"'User: ",[320,3028,767],{"class":573},[320,3030,3004],{"class":770},[320,3032,3007],{"class":573},[320,3034,2535],{"class":770},[320,3036,566],{"class":573},[320,3038,363],{"class":770},[320,3040,779],{"class":573},[320,3042,782],{"class":349},[320,3044,1369],{"class":573},[320,3046,552],{"class":326},[300,3048],{},[303,3050,3052],{"id":3051},"_7-sign-out","7. Sign out",[311,3054,3056],{"className":535,"code":3055,"language":538,"meta":316,"style":316},"await Authyra.instance.signOut();\n// authStateChanges emits AuthState.unauthenticated() → router navigates to /login\n",[282,3057,3058,3077],{"__ignoreMap":316},[320,3059,3060,3062,3064,3066,3068,3070,3073,3075],{"class":322,"line":323},[320,3061,1380],{"class":599},[320,3063,1218],{"class":563},[320,3065,566],{"class":326},[320,3067,1647],{"class":573},[320,3069,566],{"class":326},[320,3071,3072],{"class":569},"signOut",[320,3074,1204],{"class":573},[320,3076,552],{"class":326},[320,3078,3079],{"class":322,"line":330},[320,3080,3081],{"class":515},"// authStateChanges emits AuthState.unauthenticated() → router navigates to /login\n",[300,3083],{},[303,3085,160],{"id":3086},"testing",[271,3088,3089,3090,3093,3094,3097],{},"No backend required — use ",[282,3091,3092],{},"InMemoryStorage"," and a fake ",[282,3095,3096],{},"authorize"," callback:",[311,3099,3102],{"className":535,"code":3100,"filename":3101,"language":538,"meta":316,"style":316},"import 'package:test/test.dart';\nimport 'package:authyra/authyra.dart';\n\nconst _validEmail    = 'alice@example.com';\nconst _validPassword = 'secret';\n\nAuthyraClient _makeClient() => AuthyraClient(\n  providers: [\n    CredentialsProvider.withTokens(\n      id: 'email',\n      authorize: (creds) async {\n        if (creds?['email'] == _validEmail &&\n            creds?['password'] == _validPassword) {\n          return AuthSignInResult(\n            user: AuthUser(id: '1', email: _validEmail),\n            accessToken:  'fake-access',\n            refreshToken: 'fake-refresh',\n            expiresAt:    DateTime.now().add(const Duration(hours: 1)),\n          );\n        }\n        return null;\n      },\n    ),\n  ],\n  storage: InMemoryStorage(),\n);\n\nvoid main() {\n  late AuthyraClient client;\n\n  setUp(() async {\n    client = _makeClient();\n    await client.initialize();\n  });\n\n  test('returns user on valid credentials', () async {\n    final user = await client.signIn('email', params: {\n      'email':    _validEmail,\n      'password': _validPassword,\n    });\n    expect(user.email, _validEmail);\n  });\n\n  test('stores access token in session', () async {\n    await client.signIn('email', params: {\n      'email': _validEmail, 'password': _validPassword,\n    });\n    final token = await client.getAccessToken();\n    expect(token, 'fake-access');\n  });\n\n  test('throws on wrong password', () {\n    expect(\n      () => client.signIn('email', params: {\n        'email': _validEmail, 'password': 'wrong',\n      }),\n      throwsA(isA\u003CAuthenticationFailedException>()),\n    );\n  });\n\n  test('isAuthenticated is false after sign out', () async {\n    await client.signIn('email', params: {\n      'email': _validEmail, 'password': _validPassword,\n    });\n    await client.signOut();\n    expect(await client.isAuthenticated(), isFalse);\n  });\n}\n","test/email_auth_test.dart",[282,3103,3104,3113,3121,3125,3139,3153,3157,3172,3180,3191,3202,3215,3239,3257,3265,3292,3304,3316,3357,3364,3369,3376,3383,3389,3395,3408,3414,3418,3427,3438,3442,3453,3466,3481,3488,3492,3511,3540,3551,3562,3568,3585,3591,3595,3612,3634,3654,3660,3680,3696,3702,3706,3720,3726,3751,3770,3776,3796,3802,3808,3812,3829,3851,3869,3875,3889,3912,3918],{"__ignoreMap":316},[320,3105,3106,3108,3111],{"class":322,"line":323},[320,3107,546],{"class":545},[320,3109,3110],{"class":349}," 'package:test/test.dart'",[320,3112,552],{"class":326},[320,3114,3115,3117,3119],{"class":322,"line":330},[320,3116,546],{"class":545},[320,3118,1319],{"class":349},[320,3120,552],{"class":326},[320,3122,3123],{"class":322,"line":358},[320,3124,558],{"emptyLinePlaceholder":557},[320,3126,3127,3129,3132,3134,3137],{"class":322,"line":380},[320,3128,1290],{"class":336},[320,3130,3131],{"class":573}," _validEmail    ",[320,3133,614],{"class":326},[320,3135,3136],{"class":349}," 'alice@example.com'",[320,3138,552],{"class":326},[320,3140,3141,3143,3146,3148,3151],{"class":322,"line":402},[320,3142,1290],{"class":336},[320,3144,3145],{"class":573}," _validPassword ",[320,3147,614],{"class":326},[320,3149,3150],{"class":349}," 'secret'",[320,3152,552],{"class":326},[320,3154,3155],{"class":322,"line":423},[320,3156,558],{"emptyLinePlaceholder":557},[320,3158,3159,3161,3164,3166,3168,3170],{"class":322,"line":445},[320,3160,199],{"class":563},[320,3162,3163],{"class":569}," _makeClient",[320,3165,1187],{"class":573},[320,3167,1488],{"class":326},[320,3169,1235],{"class":563},[320,3171,574],{"class":573},[320,3173,3174,3176,3178],{"class":322,"line":466},[320,3175,1344],{"class":573},[320,3177,343],{"class":326},[320,3179,1939],{"class":573},[320,3181,3182,3185,3187,3189],{"class":322,"line":685},[320,3183,3184],{"class":563},"    CredentialsProvider",[320,3186,566],{"class":326},[320,3188,570],{"class":569},[320,3190,574],{"class":573},[320,3192,3193,3196,3198,3200],{"class":322,"line":693},[320,3194,3195],{"class":573},"      id",[320,3197,343],{"class":326},[320,3199,584],{"class":349},[320,3201,355],{"class":326},[320,3203,3204,3207,3209,3211,3213],{"class":322,"line":698},[320,3205,3206],{"class":573},"      authorize",[320,3208,343],{"class":326},[320,3210,596],{"class":573},[320,3212,600],{"class":599},[320,3214,603],{"class":573},[320,3216,3217,3220,3223,3225,3227,3229,3231,3233,3236],{"class":322,"line":730},[320,3218,3219],{"class":599},"        if",[320,3221,3222],{"class":573}," (creds",[320,3224,1574],{"class":326},[320,3226,657],{"class":573},[320,3228,660],{"class":349},[320,3230,2940],{"class":573},[320,3232,712],{"class":326},[320,3234,3235],{"class":573}," _validEmail ",[320,3237,3238],{"class":326},"&&\n",[320,3240,3241,3244,3246,3248,3250,3252,3254],{"class":322,"line":750},[320,3242,3243],{"class":573},"            creds",[320,3245,1574],{"class":326},[320,3247,657],{"class":573},[320,3249,678],{"class":349},[320,3251,2940],{"class":573},[320,3253,712],{"class":326},[320,3255,3256],{"class":573}," _validPassword) {\n",[320,3258,3259,3261,3263],{"class":322,"line":761},[320,3260,2496],{"class":599},[320,3262,824],{"class":563},[320,3264,574],{"class":573},[320,3266,3267,3270,3272,3274,3276,3278,3281,3283,3285,3287,3290],{"class":322,"line":787},[320,3268,3269],{"class":573},"            user",[320,3271,343],{"class":326},[320,3273,837],{"class":563},[320,3275,1108],{"class":573},[320,3277,343],{"class":326},[320,3279,3280],{"class":349}," '1'",[320,3282,634],{"class":326},[320,3284,1125],{"class":573},[320,3286,343],{"class":326},[320,3288,3289],{"class":573}," _validEmail)",[320,3291,355],{"class":326},[320,3293,3294,3297,3299,3302],{"class":322,"line":799},[320,3295,3296],{"class":573},"            accessToken",[320,3298,343],{"class":326},[320,3300,3301],{"class":349},"  'fake-access'",[320,3303,355],{"class":326},[320,3305,3306,3309,3311,3314],{"class":322,"line":807},[320,3307,3308],{"class":573},"            refreshToken",[320,3310,343],{"class":326},[320,3312,3313],{"class":349}," 'fake-refresh'",[320,3315,355],{"class":326},[320,3317,3318,3321,3323,3325,3327,3330,3332,3334,3337,3339,3341,3344,3347,3349,3352,3355],{"class":322,"line":813},[320,3319,3320],{"class":573},"            expiresAt",[320,3322,343],{"class":326},[320,3324,965],{"class":563},[320,3326,566],{"class":326},[320,3328,3329],{"class":569},"now",[320,3331,1204],{"class":573},[320,3333,566],{"class":326},[320,3335,3336],{"class":569},"add",[320,3338,628],{"class":573},[320,3340,1290],{"class":336},[320,3342,3343],{"class":563}," Duration",[320,3345,3346],{"class":573},"(hours",[320,3348,343],{"class":326},[320,3350,3351],{"class":545}," 1",[320,3353,3354],{"class":573},"))",[320,3356,355],{"class":326},[320,3358,3359,3362],{"class":322,"line":818},[320,3360,3361],{"class":573},"          )",[320,3363,552],{"class":326},[320,3365,3366],{"class":322,"line":829},[320,3367,3368],{"class":573},"        }\n",[320,3370,3371,3374],{"class":322,"line":842},[320,3372,3373],{"class":599},"        return",[320,3375,1099],{"class":326},[320,3377,3378,3381],{"class":322,"line":865},[320,3379,3380],{"class":573},"      }",[320,3382,355],{"class":326},[320,3384,3385,3387],{"class":322,"line":886},[320,3386,991],{"class":573},[320,3388,355],{"class":326},[320,3390,3391,3393],{"class":322,"line":908},[320,3392,2874],{"class":573},[320,3394,355],{"class":326},[320,3396,3397,3399,3401,3404,3406],{"class":322,"line":915},[320,3398,1355],{"class":573},[320,3400,343],{"class":326},[320,3402,3403],{"class":563}," InMemoryStorage",[320,3405,1204],{"class":573},[320,3407,355],{"class":326},[320,3409,3410,3412],{"class":322,"line":936},[320,3411,1369],{"class":573},[320,3413,552],{"class":326},[320,3415,3416],{"class":322,"line":957},[320,3417,558],{"emptyLinePlaceholder":557},[320,3419,3420,3422,3424],{"class":322,"line":988},[320,3421,1181],{"class":336},[320,3423,1184],{"class":569},[320,3425,3426],{"class":573},"() {\n",[320,3428,3429,3432,3434,3436],{"class":322,"line":996},[320,3430,3431],{"class":336},"  late",[320,3433,1235],{"class":563},[320,3435,1383],{"class":573},[320,3437,552],{"class":326},[320,3439,3440],{"class":322,"line":1004},[320,3441,558],{"emptyLinePlaceholder":557},[320,3443,3444,3447,3449,3451],{"class":322,"line":1811},[320,3445,3446],{"class":569},"  setUp",[320,3448,1737],{"class":573},[320,3450,600],{"class":599},[320,3452,603],{"class":573},[320,3454,3455,3458,3460,3462,3464],{"class":322,"line":1816},[320,3456,3457],{"class":573},"    client ",[320,3459,614],{"class":326},[320,3461,3163],{"class":569},[320,3463,1204],{"class":573},[320,3465,552],{"class":326},[320,3467,3468,3471,3473,3475,3477,3479],{"class":322,"line":1822},[320,3469,3470],{"class":599},"    await",[320,3472,1383],{"class":573},[320,3474,566],{"class":326},[320,3476,1223],{"class":569},[320,3478,1204],{"class":573},[320,3480,552],{"class":326},[320,3482,3483,3486],{"class":322,"line":1827},[320,3484,3485],{"class":573},"  })",[320,3487,552],{"class":326},[320,3489,3490],{"class":322,"line":1832},[320,3491,558],{"emptyLinePlaceholder":557},[320,3493,3494,3497,3499,3502,3504,3507,3509],{"class":322,"line":1849},[320,3495,3496],{"class":569},"  test",[320,3498,628],{"class":573},[320,3500,3501],{"class":349},"'returns user on valid credentials'",[320,3503,634],{"class":326},[320,3505,3506],{"class":573}," () ",[320,3508,600],{"class":599},[320,3510,603],{"class":573},[320,3512,3513,3515,3518,3520,3522,3524,3526,3528,3530,3532,3534,3536,3538],{"class":322,"line":1859},[320,3514,608],{"class":336},[320,3516,3517],{"class":573}," user ",[320,3519,614],{"class":326},[320,3521,617],{"class":599},[320,3523,1383],{"class":573},[320,3525,566],{"class":326},[320,3527,1652],{"class":569},[320,3529,628],{"class":573},[320,3531,660],{"class":349},[320,3533,634],{"class":326},[320,3535,1661],{"class":573},[320,3537,343],{"class":326},[320,3539,603],{"class":573},[320,3541,3542,3544,3546,3549],{"class":322,"line":1872},[320,3543,646],{"class":349},[320,3545,343],{"class":326},[320,3547,3548],{"class":573},"    _validEmail",[320,3550,355],{"class":326},[320,3552,3553,3555,3557,3560],{"class":322,"line":1900},[320,3554,670],{"class":349},[320,3556,343],{"class":326},[320,3558,3559],{"class":573}," _validPassword",[320,3561,355],{"class":326},[320,3563,3564,3566],{"class":322,"line":1913},[320,3565,688],{"class":573},[320,3567,552],{"class":326},[320,3569,3570,3573,3575,3577,3579,3581,3583],{"class":322,"line":1931},[320,3571,3572],{"class":569},"    expect",[320,3574,2525],{"class":573},[320,3576,566],{"class":326},[320,3578,363],{"class":573},[320,3580,634],{"class":326},[320,3582,3289],{"class":573},[320,3584,552],{"class":326},[320,3586,3587,3589],{"class":322,"line":1942},[320,3588,3485],{"class":573},[320,3590,552],{"class":326},[320,3592,3593],{"class":322,"line":1950},[320,3594,558],{"emptyLinePlaceholder":557},[320,3596,3597,3599,3601,3604,3606,3608,3610],{"class":322,"line":1963},[320,3598,3496],{"class":569},[320,3600,628],{"class":573},[320,3602,3603],{"class":349},"'stores access token in session'",[320,3605,634],{"class":326},[320,3607,3506],{"class":573},[320,3609,600],{"class":599},[320,3611,603],{"class":573},[320,3613,3614,3616,3618,3620,3622,3624,3626,3628,3630,3632],{"class":322,"line":1988},[320,3615,3470],{"class":599},[320,3617,1383],{"class":573},[320,3619,566],{"class":326},[320,3621,1652],{"class":569},[320,3623,628],{"class":573},[320,3625,660],{"class":349},[320,3627,634],{"class":326},[320,3629,1661],{"class":573},[320,3631,343],{"class":326},[320,3633,603],{"class":573},[320,3635,3636,3638,3640,3643,3645,3648,3650,3652],{"class":322,"line":2006},[320,3637,646],{"class":349},[320,3639,343],{"class":326},[320,3641,3642],{"class":573}," _validEmail",[320,3644,634],{"class":326},[320,3646,3647],{"class":349}," 'password'",[320,3649,343],{"class":326},[320,3651,3559],{"class":573},[320,3653,355],{"class":326},[320,3655,3656,3658],{"class":322,"line":2014},[320,3657,688],{"class":573},[320,3659,552],{"class":326},[320,3661,3662,3664,3666,3668,3670,3672,3674,3676,3678],{"class":322,"line":2035},[320,3663,608],{"class":336},[320,3665,2900],{"class":573},[320,3667,614],{"class":326},[320,3669,617],{"class":599},[320,3671,1383],{"class":573},[320,3673,566],{"class":326},[320,3675,2915],{"class":569},[320,3677,1204],{"class":573},[320,3679,552],{"class":326},[320,3681,3682,3684,3687,3689,3692,3694],{"class":322,"line":2042},[320,3683,3572],{"class":569},[320,3685,3686],{"class":573},"(token",[320,3688,634],{"class":326},[320,3690,3691],{"class":349}," 'fake-access'",[320,3693,1369],{"class":573},[320,3695,552],{"class":326},[320,3697,3698,3700],{"class":322,"line":2053},[320,3699,3485],{"class":573},[320,3701,552],{"class":326},[320,3703,3704],{"class":322,"line":2075},[320,3705,558],{"emptyLinePlaceholder":557},[320,3707,3708,3710,3712,3715,3717],{"class":322,"line":2086},[320,3709,3496],{"class":569},[320,3711,628],{"class":573},[320,3713,3714],{"class":349},"'throws on wrong password'",[320,3716,634],{"class":326},[320,3718,3719],{"class":573}," () {\n",[320,3721,3722,3724],{"class":322,"line":2093},[320,3723,3572],{"class":569},[320,3725,574],{"class":573},[320,3727,3728,3731,3733,3735,3737,3739,3741,3743,3745,3747,3749],{"class":322,"line":2115},[320,3729,3730],{"class":573},"      () ",[320,3732,1488],{"class":326},[320,3734,1383],{"class":573},[320,3736,566],{"class":326},[320,3738,1652],{"class":569},[320,3740,628],{"class":573},[320,3742,660],{"class":349},[320,3744,634],{"class":326},[320,3746,1661],{"class":573},[320,3748,343],{"class":326},[320,3750,603],{"class":573},[320,3752,3753,3755,3757,3759,3761,3763,3765,3768],{"class":322,"line":2133},[320,3754,1670],{"class":349},[320,3756,343],{"class":326},[320,3758,3642],{"class":573},[320,3760,634],{"class":326},[320,3762,3647],{"class":349},[320,3764,343],{"class":326},[320,3766,3767],{"class":349}," 'wrong'",[320,3769,355],{"class":326},[320,3771,3772,3774],{"class":322,"line":2170},[320,3773,1710],{"class":573},[320,3775,355],{"class":326},[320,3777,3778,3781,3783,3786,3788,3791,3794],{"class":322,"line":2178},[320,3779,3780],{"class":569},"      throwsA",[320,3782,628],{"class":573},[320,3784,3785],{"class":569},"isA",[320,3787,1474],{"class":573},[320,3789,3790],{"class":563},"AuthenticationFailedException",[320,3792,3793],{"class":573},">())",[320,3795,355],{"class":326},[320,3797,3798,3800],{"class":322,"line":2196},[320,3799,991],{"class":573},[320,3801,552],{"class":326},[320,3803,3804,3806],{"class":322,"line":2204},[320,3805,3485],{"class":573},[320,3807,552],{"class":326},[320,3809,3810],{"class":322,"line":2226},[320,3811,558],{"emptyLinePlaceholder":557},[320,3813,3814,3816,3818,3821,3823,3825,3827],{"class":322,"line":2237},[320,3815,3496],{"class":569},[320,3817,628],{"class":573},[320,3819,3820],{"class":349},"'isAuthenticated is false after sign out'",[320,3822,634],{"class":326},[320,3824,3506],{"class":573},[320,3826,600],{"class":599},[320,3828,603],{"class":573},[320,3830,3831,3833,3835,3837,3839,3841,3843,3845,3847,3849],{"class":322,"line":2251},[320,3832,3470],{"class":599},[320,3834,1383],{"class":573},[320,3836,566],{"class":326},[320,3838,1652],{"class":569},[320,3840,628],{"class":573},[320,3842,660],{"class":349},[320,3844,634],{"class":326},[320,3846,1661],{"class":573},[320,3848,343],{"class":326},[320,3850,603],{"class":573},[320,3852,3853,3855,3857,3859,3861,3863,3865,3867],{"class":322,"line":2271},[320,3854,646],{"class":349},[320,3856,343],{"class":326},[320,3858,3642],{"class":573},[320,3860,634],{"class":326},[320,3862,3647],{"class":349},[320,3864,343],{"class":326},[320,3866,3559],{"class":573},[320,3868,355],{"class":326},[320,3870,3871,3873],{"class":322,"line":2278},[320,3872,688],{"class":573},[320,3874,552],{"class":326},[320,3876,3877,3879,3881,3883,3885,3887],{"class":322,"line":2286},[320,3878,3470],{"class":599},[320,3880,1383],{"class":573},[320,3882,566],{"class":326},[320,3884,3072],{"class":569},[320,3886,1204],{"class":573},[320,3888,552],{"class":326},[320,3890,3891,3893,3895,3897,3899,3901,3903,3905,3907,3910],{"class":322,"line":2294},[320,3892,3572],{"class":569},[320,3894,628],{"class":573},[320,3896,1380],{"class":599},[320,3898,1383],{"class":573},[320,3900,566],{"class":326},[320,3902,2697],{"class":569},[320,3904,1204],{"class":573},[320,3906,634],{"class":326},[320,3908,3909],{"class":573}," isFalse)",[320,3911,552],{"class":326},[320,3913,3914,3916],{"class":322,"line":2301},[320,3915,3485],{"class":573},[320,3917,552],{"class":326},[320,3919,3920],{"class":322,"line":2308},[320,3921,469],{"class":573},[300,3923],{},[303,3925,3927],{"id":3926},"see-also","See also",[275,3929,3930,3936,3941],{},[278,3931,3932],{},[3933,3934,3935],"a",{"href":95},"Credentials Provider →",[278,3937,3938],{},[3933,3939,3940],{"href":148},"Route Protection →",[278,3942,3943],{},[3933,3944,3945],{"href":153},"Custom Provider →",[3947,3948,3949],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":316,"searchDepth":330,"depth":330,"links":3951},[3952,3953,3954,3958,3962,3963,3967,3968,3969,3970],{"id":305,"depth":330,"text":306},{"id":484,"depth":330,"text":485},{"id":526,"depth":330,"text":527,"children":3955},[3956,3957],{"id":531,"depth":358,"text":532},{"id":1010,"depth":358,"text":1011},{"id":1154,"depth":330,"text":1155,"children":3959},[3960,3961],{"id":1158,"depth":358,"text":165},{"id":1305,"depth":358,"text":1306},{"id":1396,"depth":330,"text":1397},{"id":2320,"depth":330,"text":2321,"children":3964},[3965,3966],{"id":2324,"depth":358,"text":294},{"id":2625,"depth":358,"text":2626},{"id":2887,"depth":330,"text":2888},{"id":3051,"depth":330,"text":3052},{"id":3086,"depth":330,"text":160},{"id":3926,"depth":330,"text":3927},"End-to-end guide for email and password authentication with a JWT backend.","md",null,{},{"title":3976,"description":3977},"Email Auth Guide | Authyra","Full walkthrough of email/password authentication with Authyra — from backend contract to Flutter UI and tests.","v9D23TyOIhupiE-OLq_AHr8PS2QkO0ACc34_mcvVryk",[3980,3982],{"title":114,"path":115,"stem":116,"description":3981,"children":-1},"Backend-delegated OAuth — the client secret never leaves your server.",{"title":127,"path":128,"stem":129,"description":3983,"icon":130,"children":-1},"Implémenter un provider OAuth2 custom pour n'importe quel IdP — Discord, LinkedIn, Twitter, etc.",1782700510671]