[{"data":1,"prerenderedAt":1630},["ShallowReactive",2],{"navigation_docs":3,"-troubleshooting":265,"-troubleshooting-surround":1625},[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":254,"body":267,"description":1617,"extension":1618,"links":1619,"meta":1620,"navigation":506,"path":255,"seo":1621,"stem":256,"__hash__":1624},"docs/8.troubleshooting.md",{"type":268,"value":269,"toc":1604},"minimark",[270,275,287,300,314,421,431,434,438,445,459,472,543,545,549,556,569,578,805,811,898,900,904,910,915,1057,1059,1063,1070,1081,1089,1116,1118,1122,1129,1138,1142,1228,1230,1234,1241,1255,1263,1329,1331,1338,1347,1356,1358,1362,1369,1377,1505,1511,1577,1579,1583,1600],[271,272,274],"h2",{"id":273},"notinitializedexception","NotInitializedException",[276,277,278,282,283],"p",{},[279,280,281],"strong",{},"Message",": ",[284,285,286],"code",{},"Authyra has not been initialized. Call Authyra.initialize() before accessing Authyra.instance.",[276,288,289,282,292,295,296,299],{},[279,290,291],{},"Cause",[284,293,294],{},"Authyra.instance"," was accessed before ",[284,297,298],{},"Authyra.initialize()"," completed.",[276,301,302,305,306,309,310,313],{},[279,303,304],{},"Fix",": ensure ",[284,307,308],{},"initialize"," is awaited before ",[284,311,312],{},"runApp",":",[315,316,321],"pre",{"className":317,"code":318,"language":319,"meta":320,"style":320},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","void main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await Authyra.initialize(client: client); // must be awaited\n  runApp(const MyApp());\n}\n","dart","",[284,322,323,347,367,395,415],{"__ignoreMap":320},[324,325,328,332,336,340,344],"span",{"class":326,"line":327},"line",1,[324,329,331],{"class":330},"spNyl","void",[324,333,335],{"class":334},"s2Zo4"," main",[324,337,339],{"class":338},"sTEyZ","() ",[324,341,343],{"class":342},"s7zQu","async",[324,345,346],{"class":338}," {\n",[324,348,350,354,358,361,364],{"class":326,"line":349},2,[324,351,353],{"class":352},"sBMFI","  WidgetsFlutterBinding",[324,355,357],{"class":356},"sMK4o",".",[324,359,360],{"class":334},"ensureInitialized",[324,362,363],{"class":338},"()",[324,365,366],{"class":356},";\n",[324,368,370,373,376,378,380,383,385,388,391],{"class":326,"line":369},3,[324,371,372],{"class":342},"  await",[324,374,375],{"class":352}," Authyra",[324,377,357],{"class":356},[324,379,308],{"class":334},[324,381,382],{"class":338},"(client",[324,384,313],{"class":356},[324,386,387],{"class":338}," client)",[324,389,390],{"class":356},";",[324,392,394],{"class":393},"sHwdD"," // must be awaited\n",[324,396,398,401,404,407,410,413],{"class":326,"line":397},4,[324,399,400],{"class":334},"  runApp",[324,402,403],{"class":338},"(",[324,405,406],{"class":330},"const",[324,408,409],{"class":352}," MyApp",[324,411,412],{"class":338},"())",[324,414,366],{"class":356},[324,416,418],{"class":326,"line":417},5,[324,419,420],{"class":338},"}\n",[276,422,423,424,426,427,430],{},"Also check that ",[284,425,294],{}," isn't accessed at module level (top-level variable initializers run before ",[284,428,429],{},"main",").",[432,433],"hr",{},[271,435,437],{"id":436},"providernotfoundexception","ProviderNotFoundException",[276,439,440,282,442],{},[279,441,281],{},[284,443,444],{},"No provider registered with id 'google'.",[276,446,447,282,449,452,453,456,457,357],{},[279,448,291],{},[284,450,451],{},"signIn('google', ...)"," was called but no provider with ",[284,454,455],{},"id == 'google'"," was registered with ",[284,458,199],{},[276,460,461,463,464,467,468,471],{},[279,462,304],{},": confirm the provider is in the ",[284,465,466],{},"providers"," list and the ",[284,469,470],{},"id"," matches exactly:",[315,473,475],{"className":317,"code":474,"language":319,"meta":320,"style":320},"// Provider\nGoogleProvider(clientId: '...')   // id is 'google'\n\n// Sign-in call\nawait Authyra.instance.signIn('google'); // matches ✓\n",[284,476,477,482,502,508,513],{"__ignoreMap":320},[324,478,479],{"class":326,"line":327},[324,480,481],{"class":393},"// Provider\n",[324,483,484,487,490,492,496,499],{"class":326,"line":349},[324,485,486],{"class":352},"GoogleProvider",[324,488,489],{"class":338},"(clientId",[324,491,313],{"class":356},[324,493,495],{"class":494},"sfazB"," '...'",[324,497,498],{"class":338},")   ",[324,500,501],{"class":393},"// id is 'google'\n",[324,503,504],{"class":326,"line":369},[324,505,507],{"emptyLinePlaceholder":506},true,"\n",[324,509,510],{"class":326,"line":397},[324,511,512],{"class":393},"// Sign-in call\n",[324,514,515,518,520,522,525,527,530,532,535,538,540],{"class":326,"line":417},[324,516,517],{"class":342},"await",[324,519,375],{"class":352},[324,521,357],{"class":356},[324,523,524],{"class":338},"instance",[324,526,357],{"class":356},[324,528,529],{"class":334},"signIn",[324,531,403],{"class":338},[324,533,534],{"class":494},"'google'",[324,536,537],{"class":338},")",[324,539,390],{"class":356},[324,541,542],{"class":393}," // matches ✓\n",[432,544],{},[271,546,548],{"id":547},"authenticationfailedexception","AuthenticationFailedException",[276,550,551,282,553],{},[279,552,281],{},[284,554,555],{},"Provider \"email\" returned null — credentials may be invalid.",[276,557,558,560,561,564,565,568],{},[279,559,291],{},": your ",[284,562,563],{},"authorize"," callback returned ",[284,566,567],{},"null",". This is the expected way to signal wrong credentials.",[276,570,571,574,575,577],{},[279,572,573],{},"Fix in the callback",": return ",[284,576,567],{}," only for invalid credentials; throw for infrastructure errors:",[315,579,581],{"className":317,"code":580,"language":319,"meta":320,"style":320},"authorize: (creds) async {\n  final res = await myApi.post('/auth/login', body: creds);\n\n  if (res.statusCode == 401) return null;          // wrong password → null\n  if (res.statusCode != 200) {\n    throw AuthenticationFailedException(            // server error → throw\n      'Login failed: HTTP ${res.statusCode}',\n      providerName: 'email',\n    );\n  }\n\n  return AuthSignInResult(user: AuthUser(...), ...);\n},\n",[284,582,583,596,636,640,672,691,706,733,746,754,760,765,798],{"__ignoreMap":320},[324,584,585,587,589,592,594],{"class":326,"line":327},[324,586,563],{"class":338},[324,588,313],{"class":356},[324,590,591],{"class":338}," (creds) ",[324,593,343],{"class":342},[324,595,346],{"class":338},[324,597,598,601,604,607,610,613,615,618,620,623,626,629,631,634],{"class":326,"line":349},[324,599,600],{"class":330},"  final",[324,602,603],{"class":338}," res ",[324,605,606],{"class":356},"=",[324,608,609],{"class":342}," await",[324,611,612],{"class":338}," myApi",[324,614,357],{"class":356},[324,616,617],{"class":334},"post",[324,619,403],{"class":338},[324,621,622],{"class":494},"'/auth/login'",[324,624,625],{"class":356},",",[324,627,628],{"class":338}," body",[324,630,313],{"class":356},[324,632,633],{"class":338}," creds)",[324,635,366],{"class":356},[324,637,638],{"class":326,"line":369},[324,639,507],{"emptyLinePlaceholder":506},[324,641,642,645,648,650,653,656,660,663,666,669],{"class":326,"line":397},[324,643,644],{"class":342},"  if",[324,646,647],{"class":338}," (res",[324,649,357],{"class":356},[324,651,652],{"class":338},"statusCode ",[324,654,655],{"class":356},"==",[324,657,659],{"class":658},"sbssI"," 401",[324,661,662],{"class":338},") ",[324,664,665],{"class":342},"return",[324,667,668],{"class":356}," null;",[324,670,671],{"class":393},"          // wrong password → null\n",[324,673,674,676,678,680,682,685,688],{"class":326,"line":417},[324,675,644],{"class":342},[324,677,647],{"class":338},[324,679,357],{"class":356},[324,681,652],{"class":338},[324,683,684],{"class":356},"!=",[324,686,687],{"class":658}," 200",[324,689,690],{"class":338},") {\n",[324,692,694,697,700,703],{"class":326,"line":693},6,[324,695,696],{"class":342},"    throw",[324,698,699],{"class":352}," AuthenticationFailedException",[324,701,702],{"class":338},"(            ",[324,704,705],{"class":393},"// server error → throw\n",[324,707,709,712,715,719,721,724,727,730],{"class":326,"line":708},7,[324,710,711],{"class":494},"      'Login failed: HTTP ",[324,713,714],{"class":338},"${",[324,716,718],{"class":717},"sHdIc","res",[324,720,357],{"class":338},[324,722,723],{"class":717},"statusCode",[324,725,726],{"class":338},"}",[324,728,729],{"class":494},"'",[324,731,732],{"class":356},",\n",[324,734,736,739,741,744],{"class":326,"line":735},8,[324,737,738],{"class":338},"      providerName",[324,740,313],{"class":356},[324,742,743],{"class":494}," 'email'",[324,745,732],{"class":356},[324,747,749,752],{"class":326,"line":748},9,[324,750,751],{"class":338},"    )",[324,753,366],{"class":356},[324,755,757],{"class":326,"line":756},10,[324,758,759],{"class":338},"  }\n",[324,761,763],{"class":326,"line":762},11,[324,764,507],{"emptyLinePlaceholder":506},[324,766,768,771,774,777,779,782,784,787,789,791,794,796],{"class":326,"line":767},12,[324,769,770],{"class":342},"  return",[324,772,773],{"class":352}," AuthSignInResult",[324,775,776],{"class":338},"(user",[324,778,313],{"class":356},[324,780,781],{"class":352}," AuthUser",[324,783,403],{"class":338},[324,785,786],{"class":356},"...",[324,788,537],{"class":338},[324,790,625],{"class":356},[324,792,793],{"class":356}," ...",[324,795,537],{"class":338},[324,797,366],{"class":356},[324,799,801,803],{"class":326,"line":800},13,[324,802,726],{"class":338},[324,804,732],{"class":356},[276,806,807,810],{},[279,808,809],{},"Fix in the caller",": always catch the exception in your UI:",[315,812,814],{"className":317,"code":813,"language":319,"meta":320,"style":320},"try {\n  await Authyra.instance.signIn('email', params: {...});\n} on AuthenticationFailedException {\n  setState(() => _error = 'Invalid email or password.');\n}\n",[284,815,816,823,859,871,894],{"__ignoreMap":320},[324,817,818,821],{"class":326,"line":327},[324,819,820],{"class":342},"try",[324,822,346],{"class":338},[324,824,825,827,829,831,833,835,837,839,842,844,847,849,852,854,857],{"class":326,"line":349},[324,826,372],{"class":342},[324,828,375],{"class":352},[324,830,357],{"class":356},[324,832,524],{"class":338},[324,834,357],{"class":356},[324,836,529],{"class":334},[324,838,403],{"class":338},[324,840,841],{"class":494},"'email'",[324,843,625],{"class":356},[324,845,846],{"class":338}," params",[324,848,313],{"class":356},[324,850,851],{"class":338}," {",[324,853,786],{"class":356},[324,855,856],{"class":338},"})",[324,858,366],{"class":356},[324,860,861,864,867,869],{"class":326,"line":369},[324,862,863],{"class":338},"} ",[324,865,866],{"class":342},"on",[324,868,699],{"class":352},[324,870,346],{"class":338},[324,872,873,876,879,882,885,887,890,892],{"class":326,"line":397},[324,874,875],{"class":334},"  setState",[324,877,878],{"class":338},"(() ",[324,880,881],{"class":356},"=>",[324,883,884],{"class":338}," _error ",[324,886,606],{"class":356},[324,888,889],{"class":494}," 'Invalid email or password.'",[324,891,537],{"class":338},[324,893,366],{"class":356},[324,895,896],{"class":326,"line":417},[324,897,420],{"class":338},[432,899],{},[271,901,903],{"id":902},"oauth2-callback-never-arrives","OAuth2 callback never arrives",[276,905,906,909],{},[279,907,908],{},"Symptom",": sign-in with Google/GitHub hangs; the browser opens but the app never receives the callback.",[276,911,912,313],{},[279,913,914],{},"Checklist",[916,917,918,937,992,1033,1043],"ol",{},[919,920,921,924,925,928,929,932,933,357],"li",{},[279,922,923],{},"Deep-link scheme registered"," — verify the URI scheme is in ",[284,926,927],{},"AndroidManifest.xml"," (Android) and ",[284,930,931],{},"Info.plist"," (iOS). See ",[934,935,936],"a",{"href":171},"Flutter Setup →",[919,938,939,945,946,949,950,313,953],{},[279,940,941,942],{},"Provider registered with ",[284,943,944],{},"OAuth2CallbackHandler"," — confirm ",[284,947,948],{},"registerProvider"," is called with the matching scheme prefix before ",[284,951,952],{},"Authyra.initialize",[315,954,956],{"className":317,"code":955,"language":319,"meta":320,"style":320},"OAuth2CallbackHandler.registerProvider(\n  'com.googleusercontent.apps.YOUR_ID', // must match redirect URI scheme\n  googleProvider,\n);\n",[284,957,958,969,979,986],{"__ignoreMap":320},[324,959,960,962,964,966],{"class":326,"line":327},[324,961,944],{"class":352},[324,963,357],{"class":356},[324,965,948],{"class":334},[324,967,968],{"class":338},"(\n",[324,970,971,974,976],{"class":326,"line":349},[324,972,973],{"class":494},"  'com.googleusercontent.apps.YOUR_ID'",[324,975,625],{"class":356},[324,977,978],{"class":393}," // must match redirect URI scheme\n",[324,980,981,984],{"class":326,"line":369},[324,982,983],{"class":338},"  googleProvider",[324,985,732],{"class":356},[324,987,988,990],{"class":326,"line":397},[324,989,537],{"class":338},[324,991,366],{"class":356},[919,993,994,1000,1001],{},[279,995,996,999],{},[284,997,998],{},"uriLinkStream"," forwarded"," — confirm incoming URIs reach the handler:",[315,1002,1004],{"className":317,"code":1003,"language":319,"meta":320,"style":320},"AppLinks().uriLinkStream.listen(OAuth2CallbackHandler.handleCallback);\n",[284,1005,1006],{"__ignoreMap":320},[324,1007,1008,1011,1013,1015,1017,1019,1022,1024,1026,1028,1031],{"class":326,"line":327},[324,1009,1010],{"class":352},"AppLinks",[324,1012,363],{"class":338},[324,1014,357],{"class":356},[324,1016,998],{"class":338},[324,1018,357],{"class":356},[324,1020,1021],{"class":334},"listen",[324,1023,403],{"class":338},[324,1025,944],{"class":352},[324,1027,357],{"class":356},[324,1029,1030],{"class":338},"handleCallback)",[324,1032,366],{"class":356},[919,1034,1035,1038,1039,1042],{},[279,1036,1037],{},"Redirect URI matches"," — the URI registered in the OAuth console must exactly match ",[284,1040,1041],{},"OAuth2Config.redirectUri"," (including scheme and path).",[919,1044,1045,1048,1049,1052,1053,1056],{},[279,1046,1047],{},"Timeout"," — by default ",[284,1050,1051],{},"OAuth2Config.timeout"," is 5 minutes. If the user never completes auth, ",[284,1054,1055],{},"AuthenticationCancelledException"," is thrown.",[432,1058],{},[271,1060,1062],{"id":1061},"storageexception-on-initialize","StorageException on initialize",[276,1064,1065,282,1067],{},[279,1066,281],{},[284,1068,1069],{},"StorageException: Failed to initialize storage.",[276,1071,1072,1074,1075,1077,1078,357],{},[279,1073,291],{},": the ",[284,1076,217],{}," implementation threw during ",[284,1079,1080],{},"initialize()",[276,1082,1083,313],{},[279,1084,1085,1086],{},"Common causes for ",[284,1087,1088],{},"SecureAuthStorage",[1090,1091,1092,1102,1109],"ul",{},[919,1093,1094,1095,1098,1099],{},"Android: missing ",[284,1096,1097],{},"minSdkVersion 18"," in ",[284,1100,1101],{},"android/app/build.gradle",[919,1103,1104,1105,1108],{},"iOS: missing Keychain entitlement — add ",[284,1106,1107],{},"Keychain Sharing"," capability in Xcode",[919,1110,1111,1112,1115],{},"Web: running in a context without ",[284,1113,1114],{},"localStorage"," access (e.g., private browsing with strict settings)",[432,1117],{},[271,1119,1121],{"id":1120},"tokenexpiredexception","TokenExpiredException",[276,1123,1124,282,1126],{},[279,1125,281],{},[284,1127,1128],{},"Token for user X has expired.",[276,1130,1131,1133,1134,1137],{},[279,1132,291],{},": the session's ",[284,1135,1136],{},"expiresAt"," is in the past and the provider does not support refresh (or the refresh token itself is expired).",[276,1139,1140,313],{},[279,1141,304],{},[1090,1143,1144,1151],{},[919,1145,1146,1147,1150],{},"Enable ",[284,1148,1149],{},"AuthConfig(autoRefresh: true)"," to let Authyra refresh automatically.",[919,1152,1153,1154,1156,1157],{},"Catch ",[284,1155,1121],{}," and send the user back to the login screen:",[315,1158,1160],{"className":317,"code":1159,"language":319,"meta":320,"style":320},"try {\n  final token = await Authyra.instance.getAccessToken();\n} on TokenExpiredException {\n  await Authyra.instance.signOut();\n}\n",[284,1161,1162,1168,1194,1205,1224],{"__ignoreMap":320},[324,1163,1164,1166],{"class":326,"line":327},[324,1165,820],{"class":342},[324,1167,346],{"class":338},[324,1169,1170,1172,1175,1177,1179,1181,1183,1185,1187,1190,1192],{"class":326,"line":349},[324,1171,600],{"class":330},[324,1173,1174],{"class":338}," token ",[324,1176,606],{"class":356},[324,1178,609],{"class":342},[324,1180,375],{"class":352},[324,1182,357],{"class":356},[324,1184,524],{"class":338},[324,1186,357],{"class":356},[324,1188,1189],{"class":334},"getAccessToken",[324,1191,363],{"class":338},[324,1193,366],{"class":356},[324,1195,1196,1198,1200,1203],{"class":326,"line":369},[324,1197,863],{"class":338},[324,1199,866],{"class":342},[324,1201,1202],{"class":352}," TokenExpiredException",[324,1204,346],{"class":338},[324,1206,1207,1209,1211,1213,1215,1217,1220,1222],{"class":326,"line":397},[324,1208,372],{"class":342},[324,1210,375],{"class":352},[324,1212,357],{"class":356},[324,1214,524],{"class":338},[324,1216,357],{"class":356},[324,1218,1219],{"class":334},"signOut",[324,1221,363],{"class":338},[324,1223,366],{"class":356},[324,1225,1226],{"class":326,"line":417},[324,1227,420],{"class":338},[432,1229],{},[271,1231,1233],{"id":1232},"provideralreadyregisteredexception","ProviderAlreadyRegisteredException",[276,1235,1236,282,1238],{},[279,1237,281],{},[284,1239,1240],{},"A provider with id 'email' is already registered.",[276,1242,1243,1245,1246,1248,1249,1251,1252,1254],{},[279,1244,291],{},": two providers with the same ",[284,1247,470],{}," were added to ",[284,1250,199],{},", or ",[284,1253,948],{}," was called twice with the same id.",[276,1256,1257,1259,1260,1262],{},[279,1258,304],{},": ensure each provider has a unique ",[284,1261,470],{},". If you're dynamically adding providers, guard with a check:",[315,1264,1266],{"className":317,"code":1265,"language":319,"meta":320,"style":320},"if (!client.providers.any((p) => p.id == 'email')) {\n  client.registerProvider(myEmailProvider);\n}\n",[284,1267,1268,1311,1325],{"__ignoreMap":320},[324,1269,1270,1273,1276,1279,1282,1284,1286,1288,1291,1294,1296,1299,1301,1304,1306,1308],{"class":326,"line":327},[324,1271,1272],{"class":342},"if",[324,1274,1275],{"class":338}," (",[324,1277,1278],{"class":356},"!",[324,1280,1281],{"class":338},"client",[324,1283,357],{"class":356},[324,1285,466],{"class":338},[324,1287,357],{"class":356},[324,1289,1290],{"class":334},"any",[324,1292,1293],{"class":338},"((p) ",[324,1295,881],{"class":356},[324,1297,1298],{"class":338}," p",[324,1300,357],{"class":356},[324,1302,1303],{"class":338},"id ",[324,1305,655],{"class":356},[324,1307,743],{"class":494},[324,1309,1310],{"class":338},")) {\n",[324,1312,1313,1316,1318,1320,1323],{"class":326,"line":349},[324,1314,1315],{"class":338},"  client",[324,1317,357],{"class":356},[324,1319,948],{"class":334},[324,1321,1322],{"class":338},"(myEmailProvider)",[324,1324,366],{"class":356},[324,1326,1327],{"class":326,"line":369},[324,1328,420],{"class":338},[432,1330],{},[271,1332,1334,1337],{"id":1333},"inmemorystorage-doesnt-persist-across-restarts",[284,1335,1336],{},"InMemoryStorage"," doesn't persist across restarts",[276,1339,1340,1343,1344,1346],{},[279,1341,1342],{},"Expected behaviour"," — ",[284,1345,1336],{}," is intentionally non-persistent. It's designed for tests and development.",[276,1348,1349,1350,1352,1353,1355],{},"Use ",[284,1351,1088],{}," (Flutter) or your own ",[284,1354,217],{}," implementation (backend) for production.",[432,1357],{},[271,1359,1361],{"id":1360},"tests-fail-with-singleton-already-initialized","Tests fail with \"singleton already initialized\"",[276,1363,1364,282,1366,1368],{},[279,1365,291],{},[284,1367,294],{}," was initialized in one test and not disposed before the next test ran.",[276,1370,1371,1373,1374,313],{},[279,1372,304],{},": dispose the singleton in ",[284,1375,1376],{},"tearDown",[315,1378,1380],{"className":317,"code":1379,"language":319,"meta":320,"style":320},"setUp(() async {\n  client = AuthyraClient(providers: [...], storage: InMemoryStorage());\n  await Authyra.initialize(client: client);\n});\n\ntearDown(() async {\n  if (Authyra.isInitialized) await Authyra.instance.dispose();\n});\n",[284,1381,1382,1393,1430,1448,1454,1458,1468,1499],{"__ignoreMap":320},[324,1383,1384,1387,1389,1391],{"class":326,"line":327},[324,1385,1386],{"class":334},"setUp",[324,1388,878],{"class":338},[324,1390,343],{"class":342},[324,1392,346],{"class":338},[324,1394,1395,1398,1400,1403,1406,1408,1411,1413,1416,1418,1421,1423,1426,1428],{"class":326,"line":349},[324,1396,1397],{"class":338},"  client ",[324,1399,606],{"class":356},[324,1401,1402],{"class":352}," AuthyraClient",[324,1404,1405],{"class":338},"(providers",[324,1407,313],{"class":356},[324,1409,1410],{"class":338}," [",[324,1412,786],{"class":356},[324,1414,1415],{"class":338},"]",[324,1417,625],{"class":356},[324,1419,1420],{"class":338}," storage",[324,1422,313],{"class":356},[324,1424,1425],{"class":352}," InMemoryStorage",[324,1427,412],{"class":338},[324,1429,366],{"class":356},[324,1431,1432,1434,1436,1438,1440,1442,1444,1446],{"class":326,"line":369},[324,1433,372],{"class":342},[324,1435,375],{"class":352},[324,1437,357],{"class":356},[324,1439,308],{"class":334},[324,1441,382],{"class":338},[324,1443,313],{"class":356},[324,1445,387],{"class":338},[324,1447,366],{"class":356},[324,1449,1450,1452],{"class":326,"line":397},[324,1451,856],{"class":338},[324,1453,366],{"class":356},[324,1455,1456],{"class":326,"line":417},[324,1457,507],{"emptyLinePlaceholder":506},[324,1459,1460,1462,1464,1466],{"class":326,"line":693},[324,1461,1376],{"class":334},[324,1463,878],{"class":338},[324,1465,343],{"class":342},[324,1467,346],{"class":338},[324,1469,1470,1472,1474,1477,1479,1482,1484,1486,1488,1490,1492,1495,1497],{"class":326,"line":708},[324,1471,644],{"class":342},[324,1473,1275],{"class":338},[324,1475,1476],{"class":352},"Authyra",[324,1478,357],{"class":356},[324,1480,1481],{"class":338},"isInitialized) ",[324,1483,517],{"class":342},[324,1485,375],{"class":352},[324,1487,357],{"class":356},[324,1489,524],{"class":338},[324,1491,357],{"class":356},[324,1493,1494],{"class":334},"dispose",[324,1496,363],{"class":338},[324,1498,366],{"class":356},[324,1500,1501,1503],{"class":326,"line":735},[324,1502,856],{"class":338},[324,1504,366],{"class":356},[276,1506,1507,1508,1510],{},"Alternatively, use ",[284,1509,199],{}," directly in tests — it has no singleton and requires no teardown:",[315,1512,1514],{"className":317,"code":1513,"language":319,"meta":320,"style":320},"setUp(() async {\n  client = AuthyraClient(providers: [...], storage: InMemoryStorage());\n  await client.initialize();\n});\n",[284,1515,1516,1526,1556,1571],{"__ignoreMap":320},[324,1517,1518,1520,1522,1524],{"class":326,"line":327},[324,1519,1386],{"class":334},[324,1521,878],{"class":338},[324,1523,343],{"class":342},[324,1525,346],{"class":338},[324,1527,1528,1530,1532,1534,1536,1538,1540,1542,1544,1546,1548,1550,1552,1554],{"class":326,"line":349},[324,1529,1397],{"class":338},[324,1531,606],{"class":356},[324,1533,1402],{"class":352},[324,1535,1405],{"class":338},[324,1537,313],{"class":356},[324,1539,1410],{"class":338},[324,1541,786],{"class":356},[324,1543,1415],{"class":338},[324,1545,625],{"class":356},[324,1547,1420],{"class":338},[324,1549,313],{"class":356},[324,1551,1425],{"class":352},[324,1553,412],{"class":338},[324,1555,366],{"class":356},[324,1557,1558,1560,1563,1565,1567,1569],{"class":326,"line":369},[324,1559,372],{"class":342},[324,1561,1562],{"class":338}," client",[324,1564,357],{"class":356},[324,1566,308],{"class":334},[324,1568,363],{"class":338},[324,1570,366],{"class":356},[324,1572,1573,1575],{"class":326,"line":397},[324,1574,856],{"class":338},[324,1576,366],{"class":356},[432,1578],{},[271,1580,1582],{"id":1581},"still-stuck","Still stuck?",[1090,1584,1585,1591],{},[919,1586,1587,1588],{},"Check the ",[934,1589,1590],{"href":259},"FAQ →",[919,1592,1593,1594],{},"Open an issue on ",[934,1595,1599],{"href":1596,"rel":1597},"https://github.com/meragix/authyra/issues",[1598],"nofollow","GitHub",[1601,1602,1603],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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":320,"searchDepth":349,"depth":349,"links":1605},[1606,1607,1608,1609,1610,1611,1612,1613,1615,1616],{"id":273,"depth":349,"text":274},{"id":436,"depth":349,"text":437},{"id":547,"depth":349,"text":548},{"id":902,"depth":349,"text":903},{"id":1061,"depth":349,"text":1062},{"id":1120,"depth":349,"text":1121},{"id":1232,"depth":349,"text":1233},{"id":1333,"depth":349,"text":1614},"InMemoryStorage doesn't persist across restarts",{"id":1360,"depth":349,"text":1361},{"id":1581,"depth":349,"text":1582},"Common errors, their causes, and how to fix them.","md",null,{},{"title":1622,"description":1623},"Troubleshooting | Authyra","Fix common Authyra errors — NotInitializedException, ProviderNotFoundException, StorageException, OAuth2 callback issues, and more.","Vc9-25a86j5UtqVm8XzNFyVCtYraS-h3USdKxkanAyc",[1626,1628],{"title":250,"path":251,"stem":252,"description":1627,"icon":163,"children":-1},"Setup complet d'une suite de tests avec AuthyraClient et InMemoryStorage.",{"title":258,"path":259,"stem":260,"description":1629,"children":-1},"Frequently asked questions about Authyra.",1782700506039]