[{"data":1,"prerenderedAt":2021},["ShallowReactive",2],{"navigation_docs":3,"-faq":265,"-faq-surround":2016},[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":258,"body":267,"description":2008,"extension":2009,"links":2010,"meta":2011,"navigation":648,"path":259,"seo":2012,"stem":260,"__hash__":2015},"docs/9.faq.md",{"type":268,"value":269,"toc":1991},"minimark",[270,275,280,284,292,295,299,302,369,372,374,378,386,396,398,402,408,424,426,430,434,441,473,481,522,525,527,531,540,575,578,592,594,598,607,795,802,804,808,815,820,905,910,1082,1087,1193,1195,1199,1209,1746,1761,1819,1821,1825,1892,1903,1905,1909,1916,1973,1987],[271,272,274],"h2",{"id":273},"general","General",[276,277,279],"h3",{"id":278},"what-is-authyra","What is Authyra?",[281,282,283],"p",{},"Authyra is a pure authentication logic framework for Dart and Flutter. It handles authentication state, session management, and provider orchestration while remaining completely agnostic to your navigation and UI choices.",[281,285,286,287,291],{},"The core ",[288,289,290],"code",{},"authyra"," package has no Flutter dependency and runs identically on mobile, web, desktop, backend (Shelf, Dart Frog), and CLI tools.",[293,294],"hr",{},[276,296,298],{"id":297},"why-not-use-firebase-auth-or-supabase-auth","Why not use Firebase Auth or Supabase Auth?",[281,300,301],{},"You can — Authyra doesn't compete with BaaS platforms. The difference is:",[303,304,305,321],"table",{},[306,307,308],"thead",{},[309,310,311,315,318],"tr",{},[312,313,314],"th",{},"Aspect",[312,316,317],{},"Firebase / Supabase",[312,319,320],{},"Authyra",[322,323,324,336,347,358],"tbody",{},[309,325,326,330,333],{},[327,328,329],"td",{},"Backend",[327,331,332],{},"Managed service",[327,334,335],{},"Bring your own",[309,337,338,341,344],{},[327,339,340],{},"Auth logic",[327,342,343],{},"In the SDK",[327,345,346],{},"In your app (you own it)",[309,348,349,352,355],{},[327,350,351],{},"Navigation control",[327,353,354],{},"Opinionated",[327,356,357],{},"Fully decoupled",[309,359,360,363,366],{},[327,361,362],{},"Multi-platform",[327,364,365],{},"Flutter + limited Dart",[327,367,368],{},"Any Dart platform",[281,370,371],{},"Use Authyra when you have your own backend, want full control, or need to run the same auth logic on both a Flutter app and a Dart backend.",[293,373],{},[276,375,377],{"id":376},"is-authyra-production-ready","Is Authyra production-ready?",[281,379,380,381,385],{},"v0.1.0 is an ",[382,383,384],"strong",{},"MVP release",". The API is stable for the core features but the test suite is still being expanded. We recommend:",[387,388,389,393],"ul",{},[390,391,392],"li",{},"Using it in new projects and side projects now.",[390,394,395],{},"Waiting for v1.0.0 (targeting ≥ 90% test coverage) for mission-critical production systems.",[293,397],{},[276,399,401],{"id":400},"does-authyra-work-offline","Does Authyra work offline?",[281,403,404,405,407],{},"Session state is cached in memory and persisted to ",[288,406,217],{},". Your app can:",[387,409,410,421],{},[390,411,412,413,416,417,420],{},"Read ",[288,414,415],{},"Authyra.instance.isAuthenticated"," and ",[288,418,419],{},"currentUser"," offline — no network call required.",[390,422,423],{},"React to cached state immediately on startup, before any network request.",[293,425],{},[271,427,429],{"id":428},"technical","Technical",[276,431,433],{"id":432},"why-two-packages-core-vs-flutter","Why two packages? (core vs Flutter)",[281,435,436,440],{},[382,437,438],{},[288,439,290],{}," (pure Dart, v0.1.0):",[387,442,443,446,449,455,458],{},[390,444,445],{},"Zero Flutter dependency.",[390,447,448],{},"Works on backend, CLI, scripts.",[390,450,451,454],{},[288,452,453],{},"dart test"," runs without a Flutter device.",[390,456,457],{},"Smaller pub.dev bundle.",[390,459,460,461,464,465,464,467,464,469,472],{},"Ships: ",[288,462,463],{},"CredentialsProvider",", ",[288,466,199],{},[288,468,203],{},[288,470,471],{},"InMemoryStorage",".",[281,474,475,480],{},[382,476,477],{},[288,478,479],{},"authyra_flutter"," (Flutter, v0.1.0):",[387,482,483,489,506,516],{},[390,484,485,486,488],{},"Re-exports the entire ",[288,487,290],{}," core — one import covers everything.",[390,490,491,464,494,464,497,464,500,464,503,472],{},[288,492,493],{},"GoogleProvider",[288,495,496],{},"GitHubOAuth2Provider",[288,498,499],{},"AppleProvider",[288,501,502],{},"OAuth2Provider",[288,504,505],{},"ProxyOAuthProvider",[390,507,508,511,512,515],{},[288,509,510],{},"SecureAuthStorage"," — ",[288,513,514],{},"flutter_secure_storage","-backed implementation.",[390,517,518,521],{},[288,519,520],{},"OAuth2CallbackHandler"," — deep-link router for OAuth redirects.",[281,523,524],{},"This separation keeps the authentication core clean and reusable while the Flutter layer remains purely additive.",[293,526],{},[276,528,530],{"id":529},"can-i-use-authyra-without-flutter","Can I use Authyra without Flutter?",[281,532,533,534,536,537,539],{},"Yes. Just add ",[288,535,290],{}," (not ",[288,538,479],{},"):",[541,542,547],"pre",{"className":543,"code":544,"language":545,"meta":546,"style":546},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dependencies:\n  authyra: ^0.1.0\n","yaml","",[288,548,549,562],{"__ignoreMap":546},[550,551,554,558],"span",{"class":552,"line":553},"line",1,[550,555,557],{"class":556},"swJcz","dependencies",[550,559,561],{"class":560},"sMK4o",":\n",[550,563,565,568,571],{"class":552,"line":564},2,[550,566,567],{"class":556},"  authyra",[550,569,570],{"class":560},":",[550,572,574],{"class":573},"sfazB"," ^0.1.0\n",[281,576,577],{},"Works in:",[387,579,580,583,586,589],{},[390,581,582],{},"Dart backend services (Shelf, Dart Frog)",[390,584,585],{},"CLI tools",[390,587,588],{},"Scripts",[390,590,591],{},"Unit tests",[293,593],{},[276,595,597],{"id":596},"does-authyra-support-multi-account","Does Authyra support multi-account?",[281,599,600,601,603,604,606],{},"Yes — ",[288,602,207],{}," ships in the core (",[288,605,290],{}," package):",[541,608,612],{"className":609,"code":610,"language":611,"meta":546,"style":546},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","final mgr = Authyra.instance.accounts;\n\n// All signed-in accounts, sorted by last activity\nfinal users = await mgr.getAll();\n\n// Activate a different account\nawait mgr.switchTo(userId);\n\n// Sign out one account, keep others active\nawait mgr.signOut(userId);\n\n// Sign out every account\nawait mgr.signOutAll();\n\n// Prune expired sessions\nawait mgr.cleanExpired();\n","dart",[288,613,614,644,650,657,685,690,696,714,719,725,741,746,752,768,773,779],{"__ignoreMap":546},[550,615,616,620,624,627,631,633,636,638,641],{"class":552,"line":553},[550,617,619],{"class":618},"spNyl","final",[550,621,623],{"class":622},"sTEyZ"," mgr ",[550,625,626],{"class":560},"=",[550,628,630],{"class":629},"sBMFI"," Authyra",[550,632,472],{"class":560},[550,634,635],{"class":622},"instance",[550,637,472],{"class":560},[550,639,640],{"class":622},"accounts",[550,642,643],{"class":560},";\n",[550,645,646],{"class":552,"line":564},[550,647,649],{"emptyLinePlaceholder":648},true,"\n",[550,651,653],{"class":552,"line":652},3,[550,654,656],{"class":655},"sHwdD","// All signed-in accounts, sorted by last activity\n",[550,658,660,662,665,667,671,674,676,680,683],{"class":552,"line":659},4,[550,661,619],{"class":618},[550,663,664],{"class":622}," users ",[550,666,626],{"class":560},[550,668,670],{"class":669},"s7zQu"," await",[550,672,673],{"class":622}," mgr",[550,675,472],{"class":560},[550,677,679],{"class":678},"s2Zo4","getAll",[550,681,682],{"class":622},"()",[550,684,643],{"class":560},[550,686,688],{"class":552,"line":687},5,[550,689,649],{"emptyLinePlaceholder":648},[550,691,693],{"class":552,"line":692},6,[550,694,695],{"class":655},"// Activate a different account\n",[550,697,699,702,704,706,709,712],{"class":552,"line":698},7,[550,700,701],{"class":669},"await",[550,703,673],{"class":622},[550,705,472],{"class":560},[550,707,708],{"class":678},"switchTo",[550,710,711],{"class":622},"(userId)",[550,713,643],{"class":560},[550,715,717],{"class":552,"line":716},8,[550,718,649],{"emptyLinePlaceholder":648},[550,720,722],{"class":552,"line":721},9,[550,723,724],{"class":655},"// Sign out one account, keep others active\n",[550,726,728,730,732,734,737,739],{"class":552,"line":727},10,[550,729,701],{"class":669},[550,731,673],{"class":622},[550,733,472],{"class":560},[550,735,736],{"class":678},"signOut",[550,738,711],{"class":622},[550,740,643],{"class":560},[550,742,744],{"class":552,"line":743},11,[550,745,649],{"emptyLinePlaceholder":648},[550,747,749],{"class":552,"line":748},12,[550,750,751],{"class":655},"// Sign out every account\n",[550,753,755,757,759,761,764,766],{"class":552,"line":754},13,[550,756,701],{"class":669},[550,758,673],{"class":622},[550,760,472],{"class":560},[550,762,763],{"class":678},"signOutAll",[550,765,682],{"class":622},[550,767,643],{"class":560},[550,769,771],{"class":552,"line":770},14,[550,772,649],{"emptyLinePlaceholder":648},[550,774,776],{"class":552,"line":775},15,[550,777,778],{"class":655},"// Prune expired sessions\n",[550,780,782,784,786,788,791,793],{"class":552,"line":781},16,[550,783,701],{"class":669},[550,785,673],{"class":622},[550,787,472],{"class":560},[550,789,790],{"class":678},"cleanExpired",[550,792,682],{"class":622},[550,794,643],{"class":560},[281,796,797,798,801],{},"The number of concurrent accounts is capped by ",[288,799,800],{},"AuthConfig.maxAccounts"," (default: 5).",[293,803],{},[276,805,807],{"id":806},"can-i-use-my-own-state-management","Can I use my own state management?",[281,809,810,811,814],{},"Authyra is completely state-management-agnostic. The ",[288,812,813],{},"authStateChanges"," stream plugs into anything:",[281,816,817,570],{},[382,818,819],{},"Riverpod",[541,821,823],{"className":609,"code":822,"language":611,"meta":546,"style":546},"final authStateProvider = StreamProvider\u003CAuthState>((ref) {\n  return Authyra.instance.authStateChanges;\n});\n\n// In a widget:\nfinal state = ref.watch(authStateProvider).value;\n",[288,824,825,845,862,869,873,878],{"__ignoreMap":546},[550,826,827,829,832,834,837,840,842],{"class":552,"line":553},[550,828,619],{"class":618},[550,830,831],{"class":622}," authStateProvider ",[550,833,626],{"class":560},[550,835,836],{"class":629}," StreamProvider",[550,838,839],{"class":622},"\u003C",[550,841,226],{"class":629},[550,843,844],{"class":622},">((ref) {\n",[550,846,847,850,852,854,856,858,860],{"class":552,"line":564},[550,848,849],{"class":669},"  return",[550,851,630],{"class":629},[550,853,472],{"class":560},[550,855,635],{"class":622},[550,857,472],{"class":560},[550,859,813],{"class":622},[550,861,643],{"class":560},[550,863,864,867],{"class":552,"line":652},[550,865,866],{"class":622},"})",[550,868,643],{"class":560},[550,870,871],{"class":552,"line":659},[550,872,649],{"emptyLinePlaceholder":648},[550,874,875],{"class":552,"line":687},[550,876,877],{"class":655},"// In a widget:\n",[550,879,880,882,885,887,890,892,895,898,900,903],{"class":552,"line":692},[550,881,619],{"class":618},[550,883,884],{"class":622}," state ",[550,886,626],{"class":560},[550,888,889],{"class":622}," ref",[550,891,472],{"class":560},[550,893,894],{"class":678},"watch",[550,896,897],{"class":622},"(authStateProvider)",[550,899,472],{"class":560},[550,901,902],{"class":622},"value",[550,904,643],{"class":560},[281,906,907,570],{},[382,908,909],{},"Bloc / Cubit",[541,911,913],{"className":609,"code":912,"language":611,"meta":546,"style":546},"class AuthCubit extends Cubit\u003CAuthState> {\n  late final StreamSubscription\u003CAuthState> _sub;\n\n  AuthCubit() : super(AuthState.unauthenticated()) {\n    _sub = Authyra.instance.authStateChanges.listen(emit);\n  }\n\n  @override\n  Future\u003Cvoid> close() {\n    _sub.cancel();\n    return super.close();\n  }\n}\n",[288,914,915,936,956,960,983,1010,1015,1019,1024,1043,1057,1073,1077],{"__ignoreMap":546},[550,916,917,920,923,926,929,931,933],{"class":552,"line":553},[550,918,919],{"class":560},"class",[550,921,922],{"class":629}," AuthCubit",[550,924,925],{"class":560}," extends",[550,927,928],{"class":629}," Cubit",[550,930,839],{"class":622},[550,932,226],{"class":629},[550,934,935],{"class":622},"> {\n",[550,937,938,941,944,947,949,951,954],{"class":552,"line":564},[550,939,940],{"class":618},"  late",[550,942,943],{"class":618}," final",[550,945,946],{"class":629}," StreamSubscription",[550,948,839],{"class":622},[550,950,226],{"class":629},[550,952,953],{"class":622},"> _sub",[550,955,643],{"class":560},[550,957,958],{"class":552,"line":652},[550,959,649],{"emptyLinePlaceholder":648},[550,961,962,965,968,970,973,975,977,980],{"class":552,"line":659},[550,963,964],{"class":629},"  AuthCubit",[550,966,967],{"class":622},"() ",[550,969,570],{"class":560},[550,971,972],{"class":622}," super(",[550,974,226],{"class":629},[550,976,472],{"class":560},[550,978,979],{"class":678},"unauthenticated",[550,981,982],{"class":622},"()) {\n",[550,984,985,988,990,992,994,996,998,1000,1002,1005,1008],{"class":552,"line":687},[550,986,987],{"class":622},"    _sub ",[550,989,626],{"class":560},[550,991,630],{"class":629},[550,993,472],{"class":560},[550,995,635],{"class":622},[550,997,472],{"class":560},[550,999,813],{"class":622},[550,1001,472],{"class":560},[550,1003,1004],{"class":678},"listen",[550,1006,1007],{"class":622},"(emit)",[550,1009,643],{"class":560},[550,1011,1012],{"class":552,"line":692},[550,1013,1014],{"class":622},"  }\n",[550,1016,1017],{"class":552,"line":698},[550,1018,649],{"emptyLinePlaceholder":648},[550,1020,1021],{"class":552,"line":716},[550,1022,1023],{"class":618},"  @override\n",[550,1025,1026,1029,1031,1034,1037,1040],{"class":552,"line":721},[550,1027,1028],{"class":629},"  Future",[550,1030,839],{"class":622},[550,1032,1033],{"class":618},"void",[550,1035,1036],{"class":622},"> ",[550,1038,1039],{"class":678},"close",[550,1041,1042],{"class":622},"() {\n",[550,1044,1045,1048,1050,1053,1055],{"class":552,"line":727},[550,1046,1047],{"class":622},"    _sub",[550,1049,472],{"class":560},[550,1051,1052],{"class":678},"cancel",[550,1054,682],{"class":622},[550,1056,643],{"class":560},[550,1058,1059,1062,1065,1067,1069,1071],{"class":552,"line":743},[550,1060,1061],{"class":669},"    return",[550,1063,1064],{"class":622}," super",[550,1066,472],{"class":560},[550,1068,1039],{"class":678},[550,1070,682],{"class":622},[550,1072,643],{"class":560},[550,1074,1075],{"class":552,"line":748},[550,1076,1014],{"class":622},[550,1078,1079],{"class":552,"line":754},[550,1080,1081],{"class":622},"}\n",[281,1083,1084,570],{},[382,1085,1086],{},"GoRouter",[541,1088,1090],{"className":609,"code":1089,"language":611,"meta":546,"style":546},"GoRouter(\n  refreshListenable: StreamToListenable(Authyra.instance.authStateChanges),\n  redirect: (context, state) {\n    if (!Authyra.instance.isAuthenticated) return '/login';\n    return null;\n  },\n);\n",[288,1091,1092,1099,1126,1142,1172,1179,1186],{"__ignoreMap":546},[550,1093,1094,1096],{"class":552,"line":553},[550,1095,1086],{"class":629},[550,1097,1098],{"class":622},"(\n",[550,1100,1101,1104,1106,1109,1112,1114,1116,1118,1120,1123],{"class":552,"line":564},[550,1102,1103],{"class":622},"  refreshListenable",[550,1105,570],{"class":560},[550,1107,1108],{"class":629}," StreamToListenable",[550,1110,1111],{"class":622},"(",[550,1113,320],{"class":629},[550,1115,472],{"class":560},[550,1117,635],{"class":622},[550,1119,472],{"class":560},[550,1121,1122],{"class":622},"authStateChanges)",[550,1124,1125],{"class":560},",\n",[550,1127,1128,1131,1133,1136,1139],{"class":552,"line":652},[550,1129,1130],{"class":622},"  redirect",[550,1132,570],{"class":560},[550,1134,1135],{"class":622}," (context",[550,1137,1138],{"class":560},",",[550,1140,1141],{"class":622}," state) {\n",[550,1143,1144,1147,1150,1153,1155,1157,1159,1161,1164,1167,1170],{"class":552,"line":659},[550,1145,1146],{"class":669},"    if",[550,1148,1149],{"class":622}," (",[550,1151,1152],{"class":560},"!",[550,1154,320],{"class":629},[550,1156,472],{"class":560},[550,1158,635],{"class":622},[550,1160,472],{"class":560},[550,1162,1163],{"class":622},"isAuthenticated) ",[550,1165,1166],{"class":669},"return",[550,1168,1169],{"class":573}," '/login'",[550,1171,643],{"class":560},[550,1173,1174,1176],{"class":552,"line":687},[550,1175,1061],{"class":669},[550,1177,1178],{"class":560}," null;\n",[550,1180,1181,1184],{"class":552,"line":692},[550,1182,1183],{"class":622},"  }",[550,1185,1125],{"class":560},[550,1187,1188,1191],{"class":552,"line":698},[550,1189,1190],{"class":622},")",[550,1192,643],{"class":560},[293,1194],{},[276,1196,1198],{"id":1197},"how-do-i-test-code-that-uses-authyra","How do I test code that uses Authyra?",[281,1200,1201,1202,1204,1205,1208],{},"Use ",[288,1203,199],{}," directly — no singleton, no ",[288,1206,1207],{},"Authyra.initialize()"," required:",[541,1210,1212],{"className":609,"code":1211,"language":611,"meta":546,"style":546},"import 'package:test/test.dart';\nimport 'package:authyra/authyra.dart';\n\nvoid main() {\n  late AuthyraClient client;\n\n  setUp(() async {\n    client = AuthyraClient(\n      providers: [\n        CredentialsProvider(\n          id: 'email',\n          authorize: (creds) async {\n            if (creds?['password'] == 'secret') {\n              return AuthUser(id: '1', email: creds!['email'] as String);\n            }\n            return null;\n          },\n        ),\n      ],\n      storage: InMemoryStorage(),\n    );\n    await client.initialize();\n  });\n\n  test('sign in succeeds with correct password', () async {\n    final user = await client.signIn('email', params: {\n      'email':    'alice@example.com',\n      'password': 'secret',\n    });\n    expect(user.email, equals('alice@example.com'));\n  });\n\n  test('sign in fails with wrong password', () async {\n    expect(\n      () => client.signIn('email', params: {\n        'email':    'alice@example.com',\n        'password': 'wrong',\n      }),\n      throwsA(isA\u003CAuthenticationFailedException>()),\n    );\n  });\n}\n",[288,1213,1214,1225,1234,1238,1247,1259,1263,1277,1288,1298,1305,1317,1331,1360,1405,1410,1417,1425,1433,1441,1456,1464,1481,1489,1494,1514,1547,1560,1572,1580,1609,1616,1621,1639,1646,1673,1685,1698,1706,1727,1734,1741],{"__ignoreMap":546},[550,1215,1216,1220,1223],{"class":552,"line":553},[550,1217,1219],{"class":1218},"sbssI","import",[550,1221,1222],{"class":573}," 'package:test/test.dart'",[550,1224,643],{"class":560},[550,1226,1227,1229,1232],{"class":552,"line":564},[550,1228,1219],{"class":1218},[550,1230,1231],{"class":573}," 'package:authyra/authyra.dart'",[550,1233,643],{"class":560},[550,1235,1236],{"class":552,"line":652},[550,1237,649],{"emptyLinePlaceholder":648},[550,1239,1240,1242,1245],{"class":552,"line":659},[550,1241,1033],{"class":618},[550,1243,1244],{"class":678}," main",[550,1246,1042],{"class":622},[550,1248,1249,1251,1254,1257],{"class":552,"line":687},[550,1250,940],{"class":618},[550,1252,1253],{"class":629}," AuthyraClient",[550,1255,1256],{"class":622}," client",[550,1258,643],{"class":560},[550,1260,1261],{"class":552,"line":692},[550,1262,649],{"emptyLinePlaceholder":648},[550,1264,1265,1268,1271,1274],{"class":552,"line":698},[550,1266,1267],{"class":678},"  setUp",[550,1269,1270],{"class":622},"(() ",[550,1272,1273],{"class":669},"async",[550,1275,1276],{"class":622}," {\n",[550,1278,1279,1282,1284,1286],{"class":552,"line":716},[550,1280,1281],{"class":622},"    client ",[550,1283,626],{"class":560},[550,1285,1253],{"class":629},[550,1287,1098],{"class":622},[550,1289,1290,1293,1295],{"class":552,"line":721},[550,1291,1292],{"class":622},"      providers",[550,1294,570],{"class":560},[550,1296,1297],{"class":622}," [\n",[550,1299,1300,1303],{"class":552,"line":727},[550,1301,1302],{"class":629},"        CredentialsProvider",[550,1304,1098],{"class":622},[550,1306,1307,1310,1312,1315],{"class":552,"line":743},[550,1308,1309],{"class":622},"          id",[550,1311,570],{"class":560},[550,1313,1314],{"class":573}," 'email'",[550,1316,1125],{"class":560},[550,1318,1319,1322,1324,1327,1329],{"class":552,"line":748},[550,1320,1321],{"class":622},"          authorize",[550,1323,570],{"class":560},[550,1325,1326],{"class":622}," (creds) ",[550,1328,1273],{"class":669},[550,1330,1276],{"class":622},[550,1332,1333,1336,1339,1342,1345,1348,1351,1354,1357],{"class":552,"line":754},[550,1334,1335],{"class":669},"            if",[550,1337,1338],{"class":622}," (creds",[550,1340,1341],{"class":560},"?",[550,1343,1344],{"class":622},"[",[550,1346,1347],{"class":573},"'password'",[550,1349,1350],{"class":622},"] ",[550,1352,1353],{"class":560},"==",[550,1355,1356],{"class":573}," 'secret'",[550,1358,1359],{"class":622},") {\n",[550,1361,1362,1365,1368,1371,1373,1376,1378,1381,1383,1386,1388,1390,1393,1395,1398,1401,1403],{"class":552,"line":770},[550,1363,1364],{"class":669},"              return",[550,1366,1367],{"class":629}," AuthUser",[550,1369,1370],{"class":622},"(id",[550,1372,570],{"class":560},[550,1374,1375],{"class":573}," '1'",[550,1377,1138],{"class":560},[550,1379,1380],{"class":622}," email",[550,1382,570],{"class":560},[550,1384,1385],{"class":622}," creds",[550,1387,1152],{"class":560},[550,1389,1344],{"class":622},[550,1391,1392],{"class":573},"'email'",[550,1394,1350],{"class":622},[550,1396,1397],{"class":560},"as",[550,1399,1400],{"class":629}," String",[550,1402,1190],{"class":622},[550,1404,643],{"class":560},[550,1406,1407],{"class":552,"line":775},[550,1408,1409],{"class":622},"            }\n",[550,1411,1412,1415],{"class":552,"line":781},[550,1413,1414],{"class":669},"            return",[550,1416,1178],{"class":560},[550,1418,1420,1423],{"class":552,"line":1419},17,[550,1421,1422],{"class":622},"          }",[550,1424,1125],{"class":560},[550,1426,1428,1431],{"class":552,"line":1427},18,[550,1429,1430],{"class":622},"        )",[550,1432,1125],{"class":560},[550,1434,1436,1439],{"class":552,"line":1435},19,[550,1437,1438],{"class":622},"      ]",[550,1440,1125],{"class":560},[550,1442,1444,1447,1449,1452,1454],{"class":552,"line":1443},20,[550,1445,1446],{"class":622},"      storage",[550,1448,570],{"class":560},[550,1450,1451],{"class":629}," InMemoryStorage",[550,1453,682],{"class":622},[550,1455,1125],{"class":560},[550,1457,1459,1462],{"class":552,"line":1458},21,[550,1460,1461],{"class":622},"    )",[550,1463,643],{"class":560},[550,1465,1467,1470,1472,1474,1477,1479],{"class":552,"line":1466},22,[550,1468,1469],{"class":669},"    await",[550,1471,1256],{"class":622},[550,1473,472],{"class":560},[550,1475,1476],{"class":678},"initialize",[550,1478,682],{"class":622},[550,1480,643],{"class":560},[550,1482,1484,1487],{"class":552,"line":1483},23,[550,1485,1486],{"class":622},"  })",[550,1488,643],{"class":560},[550,1490,1492],{"class":552,"line":1491},24,[550,1493,649],{"emptyLinePlaceholder":648},[550,1495,1497,1500,1502,1505,1507,1510,1512],{"class":552,"line":1496},25,[550,1498,1499],{"class":678},"  test",[550,1501,1111],{"class":622},[550,1503,1504],{"class":573},"'sign in succeeds with correct password'",[550,1506,1138],{"class":560},[550,1508,1509],{"class":622}," () ",[550,1511,1273],{"class":669},[550,1513,1276],{"class":622},[550,1515,1517,1520,1523,1525,1527,1529,1531,1534,1536,1538,1540,1543,1545],{"class":552,"line":1516},26,[550,1518,1519],{"class":618},"    final",[550,1521,1522],{"class":622}," user ",[550,1524,626],{"class":560},[550,1526,670],{"class":669},[550,1528,1256],{"class":622},[550,1530,472],{"class":560},[550,1532,1533],{"class":678},"signIn",[550,1535,1111],{"class":622},[550,1537,1392],{"class":573},[550,1539,1138],{"class":560},[550,1541,1542],{"class":622}," params",[550,1544,570],{"class":560},[550,1546,1276],{"class":622},[550,1548,1550,1553,1555,1558],{"class":552,"line":1549},27,[550,1551,1552],{"class":573},"      'email'",[550,1554,570],{"class":560},[550,1556,1557],{"class":573},"    'alice@example.com'",[550,1559,1125],{"class":560},[550,1561,1563,1566,1568,1570],{"class":552,"line":1562},28,[550,1564,1565],{"class":573},"      'password'",[550,1567,570],{"class":560},[550,1569,1356],{"class":573},[550,1571,1125],{"class":560},[550,1573,1575,1578],{"class":552,"line":1574},29,[550,1576,1577],{"class":622},"    })",[550,1579,643],{"class":560},[550,1581,1583,1586,1589,1591,1594,1596,1599,1601,1604,1607],{"class":552,"line":1582},30,[550,1584,1585],{"class":678},"    expect",[550,1587,1588],{"class":622},"(user",[550,1590,472],{"class":560},[550,1592,1593],{"class":622},"email",[550,1595,1138],{"class":560},[550,1597,1598],{"class":678}," equals",[550,1600,1111],{"class":622},[550,1602,1603],{"class":573},"'alice@example.com'",[550,1605,1606],{"class":622},"))",[550,1608,643],{"class":560},[550,1610,1612,1614],{"class":552,"line":1611},31,[550,1613,1486],{"class":622},[550,1615,643],{"class":560},[550,1617,1619],{"class":552,"line":1618},32,[550,1620,649],{"emptyLinePlaceholder":648},[550,1622,1624,1626,1628,1631,1633,1635,1637],{"class":552,"line":1623},33,[550,1625,1499],{"class":678},[550,1627,1111],{"class":622},[550,1629,1630],{"class":573},"'sign in fails with wrong password'",[550,1632,1138],{"class":560},[550,1634,1509],{"class":622},[550,1636,1273],{"class":669},[550,1638,1276],{"class":622},[550,1640,1642,1644],{"class":552,"line":1641},34,[550,1643,1585],{"class":678},[550,1645,1098],{"class":622},[550,1647,1649,1652,1655,1657,1659,1661,1663,1665,1667,1669,1671],{"class":552,"line":1648},35,[550,1650,1651],{"class":622},"      () ",[550,1653,1654],{"class":560},"=>",[550,1656,1256],{"class":622},[550,1658,472],{"class":560},[550,1660,1533],{"class":678},[550,1662,1111],{"class":622},[550,1664,1392],{"class":573},[550,1666,1138],{"class":560},[550,1668,1542],{"class":622},[550,1670,570],{"class":560},[550,1672,1276],{"class":622},[550,1674,1676,1679,1681,1683],{"class":552,"line":1675},36,[550,1677,1678],{"class":573},"        'email'",[550,1680,570],{"class":560},[550,1682,1557],{"class":573},[550,1684,1125],{"class":560},[550,1686,1688,1691,1693,1696],{"class":552,"line":1687},37,[550,1689,1690],{"class":573},"        'password'",[550,1692,570],{"class":560},[550,1694,1695],{"class":573}," 'wrong'",[550,1697,1125],{"class":560},[550,1699,1701,1704],{"class":552,"line":1700},38,[550,1702,1703],{"class":622},"      })",[550,1705,1125],{"class":560},[550,1707,1709,1712,1714,1717,1719,1722,1725],{"class":552,"line":1708},39,[550,1710,1711],{"class":678},"      throwsA",[550,1713,1111],{"class":622},[550,1715,1716],{"class":678},"isA",[550,1718,839],{"class":622},[550,1720,1721],{"class":629},"AuthenticationFailedException",[550,1723,1724],{"class":622},">())",[550,1726,1125],{"class":560},[550,1728,1730,1732],{"class":552,"line":1729},40,[550,1731,1461],{"class":622},[550,1733,643],{"class":560},[550,1735,1737,1739],{"class":552,"line":1736},41,[550,1738,1486],{"class":622},[550,1740,643],{"class":560},[550,1742,1744],{"class":552,"line":1743},42,[550,1745,1081],{"class":622},[281,1747,1748,1749,1752,1753,1756,1757,1760],{},"If your test code uses ",[288,1750,1751],{},"Authyra.instance",", call ",[288,1754,1755],{},"dispose()"," in ",[288,1758,1759],{},"tearDown"," to reset the singleton between tests:",[541,1762,1764],{"className":609,"code":1763,"language":611,"meta":546,"style":546},"tearDown(() async {\n  if (Authyra.isInitialized) {\n    await Authyra.instance.dispose();\n  }\n});\n",[288,1765,1766,1776,1790,1809,1813],{"__ignoreMap":546},[550,1767,1768,1770,1772,1774],{"class":552,"line":553},[550,1769,1759],{"class":678},[550,1771,1270],{"class":622},[550,1773,1273],{"class":669},[550,1775,1276],{"class":622},[550,1777,1778,1781,1783,1785,1787],{"class":552,"line":564},[550,1779,1780],{"class":669},"  if",[550,1782,1149],{"class":622},[550,1784,320],{"class":629},[550,1786,472],{"class":560},[550,1788,1789],{"class":622},"isInitialized) {\n",[550,1791,1792,1794,1796,1798,1800,1802,1805,1807],{"class":552,"line":652},[550,1793,1469],{"class":669},[550,1795,630],{"class":629},[550,1797,472],{"class":560},[550,1799,635],{"class":622},[550,1801,472],{"class":560},[550,1803,1804],{"class":678},"dispose",[550,1806,682],{"class":622},[550,1808,643],{"class":560},[550,1810,1811],{"class":552,"line":659},[550,1812,1014],{"class":622},[550,1814,1815,1817],{"class":552,"line":687},[550,1816,866],{"class":622},[550,1818,643],{"class":560},[293,1820],{},[276,1822,1824],{"id":1823},"what-storage-backend-should-i-use","What storage backend should I use?",[303,1826,1827,1837],{},[306,1828,1829],{},[309,1830,1831,1834],{},[312,1832,1833],{},"Runtime",[312,1835,1836],{},"Recommended",[322,1838,1839,1851,1864,1876,1884],{},[309,1840,1841,1844],{},[327,1842,1843],{},"Tests / dev",[327,1845,1846,1848,1849,1190],{},[288,1847,471],{}," (bundled with ",[288,1850,290],{},[309,1852,1853,1856],{},[327,1854,1855],{},"Flutter mobile",[327,1857,1858,1860,1861,1863],{},[288,1859,510],{}," from ",[288,1862,479],{}," (Keychain / Keystore)",[309,1865,1866,1869],{},[327,1867,1868],{},"Flutter web",[327,1870,1871,1860,1873,1875],{},[288,1872,510],{},[288,1874,479],{}," (Web Crypto)",[309,1877,1878,1881],{},[327,1879,1880],{},"Dart CLI",[327,1882,1883],{},"Encrypted file or OS keyring",[309,1885,1886,1889],{},[327,1887,1888],{},"Backend / Shelf",[327,1890,1891],{},"Redis, encrypted DB column, or a secrets manager",[281,1893,1894,1895,1898,1899,1902],{},"Never store tokens in ",[288,1896,1897],{},"SharedPreferences"," or browser ",[288,1900,1901],{},"localStorage"," — they are not encrypted.",[293,1904],{},[276,1906,1908],{"id":1907},"how-does-token-refresh-work","How does token refresh work?",[281,1910,1911,1912,1915],{},"When ",[288,1913,1914],{},"AuthyraClient.refreshSession()"," is called (manually or triggered by an API 401):",[1917,1918,1919,1925,1943,1958,1965],"ol",{},[390,1920,1921,1922,1924],{},"The active ",[288,1923,222],{}," is retrieved.",[390,1926,1927,1928,1931,1932,1935,1936,1939,1940,472],{},"If ",[288,1929,1930],{},"session.shouldRefresh"," is ",[288,1933,1934],{},"true"," (token expires within ",[288,1937,1938],{},"AuthConfig.refreshBeforeExpiry","), the client calls ",[288,1941,1942],{},"provider.refreshToken(session.refreshToken)",[390,1944,1945,1946,1949,1950,1953,1954,1957],{},"The provider returns ",[288,1947,1948],{},"AuthTokenResult"," with the new ",[288,1951,1952],{},"accessToken"," (and optionally a new ",[288,1955,1956],{},"refreshToken",").",[390,1959,1960,1961,1964],{},"The session is updated in ",[288,1962,1963],{},"SessionManager"," and re-persisted to storage.",[390,1966,1967,1969,1970,472],{},[288,1968,813],{}," emits the refreshed ",[288,1971,1972],{},"AuthState.authenticated",[281,1974,1975,1976,1978,1979,1982,1983,1986],{},"If the refresh token is itself expired or invalid, ",[288,1977,1956],{}," returns ",[288,1980,1981],{},"null",", the session is cleared, and ",[288,1984,1985],{},"AuthState.unauthenticated()"," is emitted.",[1988,1989,1990],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":546,"searchDepth":564,"depth":564,"links":1992},[1993,1999],{"id":273,"depth":564,"text":274,"children":1994},[1995,1996,1997,1998],{"id":278,"depth":652,"text":279},{"id":297,"depth":652,"text":298},{"id":376,"depth":652,"text":377},{"id":400,"depth":652,"text":401},{"id":428,"depth":564,"text":429,"children":2000},[2001,2002,2003,2004,2005,2006,2007],{"id":432,"depth":652,"text":433},{"id":529,"depth":652,"text":530},{"id":596,"depth":652,"text":597},{"id":806,"depth":652,"text":807},{"id":1197,"depth":652,"text":1198},{"id":1823,"depth":652,"text":1824},{"id":1907,"depth":652,"text":1908},"Frequently asked questions about Authyra.","md",null,{},{"title":2013,"description":2014},"FAQ | Authyra","Answers to common questions about Authyra's design, scope, and usage.","gNNA7eTWSnKGyhEVMXJZBjYwRxjhS62dnCVMBQOFoL4",[2017,2019],{"title":254,"path":255,"stem":256,"description":2018,"children":-1},"Common errors, their causes, and how to fix them.",{"title":262,"path":263,"stem":264,"description":2020,"children":-1},"...",1782700506039]