[{"data":1,"prerenderedAt":2049},["ShallowReactive",2],{"navigation_docs":3,"-core-concepts-providers":265,"-core-concepts-providers-surround":2044},[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":60,"body":267,"description":2035,"extension":2036,"links":2037,"meta":2038,"navigation":2039,"path":61,"seo":2040,"stem":62,"__hash__":2043},"docs/2.core-concepts/2.providers.md",{"type":268,"value":269,"toc":2023},"minimark",[270,297,300,305,549,685,687,691,700,769,771,775,779,785,858,871,874,879,934,936,940,1108,1110,1114,1120,1859,1865,1914,1916,1920,1990,1992,1996,2019],[271,272,273,274,277,278,280,281,284,285,288,289,292,293,296],"p",{},"Every authentication strategy in Authyra implements the ",[275,276,212],"code",{}," interface. ",[275,279,199],{}," registers providers by ",[275,282,283],{},"id"," and delegates ",[275,286,287],{},"signIn",", ",[275,290,291],{},"signOut",", and ",[275,294,295],{},"refreshToken"," to the matching provider at runtime.",[298,299],"hr",{},[301,302,304],"h2",{"id":303},"authprovider-interface","AuthProvider interface",[306,307,312],"pre",{"className":308,"code":309,"language":310,"meta":311,"style":311},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","abstract class AuthProvider {\n  String get id;                           // unique slug, e.g. 'google'\n  String get name => id;                   // display name for logs/UI\n  AuthProviderType get type => AuthProviderType.custom;\n  bool get supportsRefresh => false;\n  bool get supportsSignOut => false;\n\n  Future\u003CAuthSignInResult?> signIn({Map\u003CString, dynamic>? params});\n  Future\u003Cvoid>              signOut({String? userId}) async {}\n  Future\u003CAuthTokenResult?>  refreshToken(String refreshToken) async => null;\n}\n","dart","",[275,313,314,334,353,373,398,414,428,435,480,512,543],{"__ignoreMap":311},[315,316,319,323,326,330],"span",{"class":317,"line":318},"line",1,[315,320,322],{"class":321},"sMK4o","abstract",[315,324,325],{"class":321}," class",[315,327,329],{"class":328},"sBMFI"," AuthProvider",[315,331,333],{"class":332},"sTEyZ"," {\n",[315,335,337,340,343,346,349],{"class":317,"line":336},2,[315,338,339],{"class":328},"  String",[315,341,342],{"class":321}," get",[315,344,345],{"class":332}," id",[315,347,348],{"class":321},";",[315,350,352],{"class":351},"sHwdD","                           // unique slug, e.g. 'google'\n",[315,354,356,358,360,363,366,368,370],{"class":317,"line":355},3,[315,357,339],{"class":328},[315,359,342],{"class":321},[315,361,362],{"class":332}," name ",[315,364,365],{"class":321},"=>",[315,367,345],{"class":332},[315,369,348],{"class":321},[315,371,372],{"class":351},"                   // display name for logs/UI\n",[315,374,376,379,381,384,386,389,392,395],{"class":317,"line":375},4,[315,377,378],{"class":328},"  AuthProviderType",[315,380,342],{"class":321},[315,382,383],{"class":332}," type ",[315,385,365],{"class":321},[315,387,388],{"class":328}," AuthProviderType",[315,390,391],{"class":321},".",[315,393,394],{"class":332},"custom",[315,396,397],{"class":321},";\n",[315,399,401,404,406,409,411],{"class":317,"line":400},5,[315,402,403],{"class":328},"  bool",[315,405,342],{"class":321},[315,407,408],{"class":332}," supportsRefresh ",[315,410,365],{"class":321},[315,412,413],{"class":321}," false;\n",[315,415,417,419,421,424,426],{"class":317,"line":416},6,[315,418,403],{"class":328},[315,420,342],{"class":321},[315,422,423],{"class":332}," supportsSignOut ",[315,425,365],{"class":321},[315,427,413],{"class":321},[315,429,431],{"class":317,"line":430},7,[315,432,434],{"emptyLinePlaceholder":433},true,"\n",[315,436,438,441,444,447,450,453,456,459,461,464,466,469,472,475,478],{"class":317,"line":437},8,[315,439,440],{"class":328},"  Future",[315,442,443],{"class":332},"\u003C",[315,445,446],{"class":328},"AuthSignInResult",[315,448,449],{"class":332},"?> ",[315,451,287],{"class":452},"s2Zo4",[315,454,455],{"class":332},"({",[315,457,458],{"class":328},"Map",[315,460,443],{"class":332},[315,462,463],{"class":328},"String",[315,465,288],{"class":332},[315,467,468],{"class":328},"dynamic",[315,470,471],{"class":332},">",[315,473,474],{"class":321},"?",[315,476,477],{"class":332}," params})",[315,479,397],{"class":321},[315,481,483,485,487,491,494,496,498,500,502,505,509],{"class":317,"line":482},9,[315,484,440],{"class":328},[315,486,443],{"class":332},[315,488,490],{"class":489},"spNyl","void",[315,492,493],{"class":332},">              ",[315,495,291],{"class":452},[315,497,455],{"class":332},[315,499,463],{"class":328},[315,501,474],{"class":321},[315,503,504],{"class":332}," userId}) ",[315,506,508],{"class":507},"s7zQu","async",[315,510,511],{"class":332}," {}\n",[315,513,515,517,519,522,525,527,530,532,535,537,540],{"class":317,"line":514},10,[315,516,440],{"class":328},[315,518,443],{"class":332},[315,520,521],{"class":328},"AuthTokenResult",[315,523,524],{"class":332},"?>  ",[315,526,295],{"class":452},[315,528,529],{"class":332},"(",[315,531,463],{"class":328},[315,533,534],{"class":332}," refreshToken) ",[315,536,508],{"class":507},[315,538,539],{"class":321}," =>",[315,541,542],{"class":321}," null;\n",[315,544,546],{"class":317,"line":545},11,[315,547,548],{"class":332},"}\n",[550,551,552,568],"table",{},[553,554,555],"thead",{},[556,557,558,562,565],"tr",{},[559,560,561],"th",{},"Member",[559,563,564],{},"Required",[559,566,567],{},"Description",[569,570,571,586,601,613,628,642,657,671],"tbody",{},[556,572,573,578,581],{},[574,575,576],"td",{},[275,577,283],{},[574,579,580],{},"yes",[574,582,583,584],{},"Unique lowercase slug within an ",[275,585,199],{},[556,587,588,593,596],{},[574,589,590],{},[275,591,592],{},"name",[574,594,595],{},"no",[574,597,598,599],{},"Human-readable label — defaults to ",[275,600,283],{},[556,602,603,608,610],{},[574,604,605],{},[275,606,607],{},"type",[574,609,595],{},[574,611,612],{},"Strategy discriminant — used in logging and validation",[556,614,615,620,622],{},[574,616,617],{},[275,618,619],{},"supportsRefresh",[574,621,595],{},[574,623,624,625],{},"Opt-in to silent token renewal. Default: ",[275,626,627],{},"false",[556,629,630,635,637],{},[574,631,632],{},[275,633,634],{},"supportsSignOut",[574,636,595],{},[574,638,639,640],{},"Opt-in to server-side revocation on sign-out. Default: ",[275,641,627],{},[556,643,644,648,650],{},[574,645,646],{},[275,647,287],{},[574,649,580],{},[574,651,652,653,656],{},"Authenticate the user; return ",[275,654,655],{},"null"," on credential failure",[556,658,659,663,665],{},[574,660,661],{},[275,662,291],{},[574,664,595],{},[574,666,667,668],{},"Revoke server-side credentials — only called when ",[275,669,670],{},"supportsSignOut: true",[556,672,673,677,679],{},[574,674,675],{},[275,676,295],{},[574,678,595],{},[574,680,681,682],{},"Exchange a refresh token for new tokens — only called when ",[275,683,684],{},"supportsRefresh: true",[298,686],{},[301,688,690],{"id":689},"provider-types","Provider types",[271,692,693,696,697,699],{},[275,694,695],{},"AuthProviderType"," communicates the authentication strategy to ",[275,698,199],{},":",[306,701,703],{"className":308,"code":702,"language":310,"meta":311,"style":311},"enum AuthProviderType {\n  credentials,  // email/password or any form-based flow\n  oauth2,       // OAuth 2.0 / OIDC Authorization Code\n  magicLink,    // passwordless email flow\n  phone,        // SMS one-time-password\n  custom,       // anything else\n}\n",[275,704,705,714,725,735,745,755,765],{"__ignoreMap":311},[315,706,707,710,712],{"class":317,"line":318},[315,708,709],{"class":321},"enum",[315,711,388],{"class":328},[315,713,333],{"class":332},[315,715,716,719,722],{"class":317,"line":336},[315,717,718],{"class":332},"  credentials",[315,720,721],{"class":321},",",[315,723,724],{"class":351},"  // email/password or any form-based flow\n",[315,726,727,730,732],{"class":317,"line":355},[315,728,729],{"class":332},"  oauth2",[315,731,721],{"class":321},[315,733,734],{"class":351},"       // OAuth 2.0 / OIDC Authorization Code\n",[315,736,737,740,742],{"class":317,"line":375},[315,738,739],{"class":332},"  magicLink",[315,741,721],{"class":321},[315,743,744],{"class":351},"    // passwordless email flow\n",[315,746,747,750,752],{"class":317,"line":400},[315,748,749],{"class":332},"  phone",[315,751,721],{"class":321},[315,753,754],{"class":351},"        // SMS one-time-password\n",[315,756,757,760,762],{"class":317,"line":416},[315,758,759],{"class":332},"  custom",[315,761,721],{"class":321},[315,763,764],{"class":351},"       // anything else\n",[315,766,767],{"class":317,"line":430},[315,768,548],{"class":332},[298,770],{},[301,772,774],{"id":773},"result-types","Result types",[776,777,446],"h3",{"id":778},"authsigninresult",[271,780,781,782,784],{},"Returned by ",[275,783,287],{},". Carries the user profile and any tokens the provider received.",[306,786,788],{"className":308,"code":787,"language":310,"meta":311,"style":311},"class AuthSignInResult {\n  final AuthUser  user;\n  final String?   accessToken;\n  final String?   refreshToken;\n  final DateTime? expiresAt;\n}\n",[275,789,790,800,813,827,840,854],{"__ignoreMap":311},[315,791,792,795,798],{"class":317,"line":318},[315,793,794],{"class":321},"class",[315,796,797],{"class":328}," AuthSignInResult",[315,799,333],{"class":332},[315,801,802,805,808,811],{"class":317,"line":336},[315,803,804],{"class":489},"  final",[315,806,807],{"class":328}," AuthUser",[315,809,810],{"class":332},"  user",[315,812,397],{"class":321},[315,814,815,817,820,822,825],{"class":317,"line":355},[315,816,804],{"class":489},[315,818,819],{"class":328}," String",[315,821,474],{"class":321},[315,823,824],{"class":332},"   accessToken",[315,826,397],{"class":321},[315,828,829,831,833,835,838],{"class":317,"line":375},[315,830,804],{"class":489},[315,832,819],{"class":328},[315,834,474],{"class":321},[315,836,837],{"class":332},"   refreshToken",[315,839,397],{"class":321},[315,841,842,844,847,849,852],{"class":317,"line":400},[315,843,804],{"class":489},[315,845,846],{"class":328}," DateTime",[315,848,474],{"class":321},[315,850,851],{"class":332}," expiresAt",[315,853,397],{"class":321},[315,855,856],{"class":317,"line":416},[315,857,548],{"class":332},[271,859,860,861,863,864,866,867,870],{},"Tokens are optional — omit them for server-side session flows (cookie auth) where tokens are managed opaquely by the backend. When present, ",[275,862,199],{}," stores them in ",[275,865,222],{},", enabling ",[275,868,869],{},"getAccessToken()"," and silent refresh.",[776,872,521],{"id":873},"authtokenresult",[271,875,781,876,878],{},[275,877,295],{},". Token-only — the existing user profile is preserved.",[306,880,882],{"className":308,"code":881,"language":310,"meta":311,"style":311},"class AuthTokenResult {\n  final String    accessToken;\n  final String?   refreshToken;  // null = keep existing refresh token\n  final DateTime  expiresAt;\n}\n",[275,883,884,893,904,919,930],{"__ignoreMap":311},[315,885,886,888,891],{"class":317,"line":318},[315,887,794],{"class":321},[315,889,890],{"class":328}," AuthTokenResult",[315,892,333],{"class":332},[315,894,895,897,899,902],{"class":317,"line":336},[315,896,804],{"class":489},[315,898,819],{"class":328},[315,900,901],{"class":332},"    accessToken",[315,903,397],{"class":321},[315,905,906,908,910,912,914,916],{"class":317,"line":355},[315,907,804],{"class":489},[315,909,819],{"class":328},[315,911,474],{"class":321},[315,913,837],{"class":332},[315,915,348],{"class":321},[315,917,918],{"class":351},"  // null = keep existing refresh token\n",[315,920,921,923,925,928],{"class":317,"line":375},[315,922,804],{"class":489},[315,924,846],{"class":328},[315,926,927],{"class":332},"  expiresAt",[315,929,397],{"class":321},[315,931,932],{"class":317,"line":400},[315,933,548],{"class":332},[298,935],{},[301,937,939],{"id":938},"built-in-providers","Built-in providers",[550,941,942,961],{},[553,943,944],{},[556,945,946,949,952,955,958],{},[559,947,948],{},"Provider",[559,950,951],{},"Package",[559,953,954],{},"Type",[559,956,957],{},"PKCE",[559,959,960],{},"Client secret",[569,962,963,985,1004,1027,1047,1068,1088],{},[556,964,965,970,975,980,983],{},[574,966,967],{},[275,968,969],{},"CredentialsProvider",[574,971,972],{},[275,973,974],{},"authyra",[574,976,977],{},[275,978,979],{},"credentials",[574,981,982],{},"—",[574,984,982],{},[556,986,987,992,996,1000,1002],{},[574,988,989],{},[275,990,991],{},"CredentialsProvider.withTokens",[574,993,994],{},[275,995,974],{},[574,997,998],{},[275,999,979],{},[574,1001,982],{},[574,1003,982],{},[556,1005,1006,1011,1016,1021,1024],{},[574,1007,1008],{},[275,1009,1010],{},"OAuth2Provider",[574,1012,1013],{},[275,1014,1015],{},"authyra_flutter",[574,1017,1018],{},[275,1019,1020],{},"oauth2",[574,1022,1023],{},"✓ (default)",[574,1025,1026],{},"optional",[556,1028,1029,1034,1038,1042,1045],{},[574,1030,1031],{},[275,1032,1033],{},"GoogleProvider",[574,1035,1036],{},[275,1037,1015],{},[574,1039,1040],{},[275,1041,1020],{},[574,1043,1044],{},"✓",[574,1046,1026],{},[556,1048,1049,1054,1058,1062,1065],{},[574,1050,1051],{},[275,1052,1053],{},"GitHubOAuth2Provider",[574,1055,1056],{},[275,1057,1015],{},[574,1059,1060],{},[275,1061,1020],{},[574,1063,1064],{},"✗",[574,1066,1067],{},"required",[556,1069,1070,1075,1079,1083,1085],{},[574,1071,1072],{},[275,1073,1074],{},"AppleProvider",[574,1076,1077],{},[275,1078,1015],{},[574,1080,1081],{},[275,1082,1020],{},[574,1084,1044],{},[574,1086,1087],{},"ES256 JWT",[556,1089,1090,1095,1099,1103,1105],{},[574,1091,1092],{},[275,1093,1094],{},"ProxyOAuthProvider",[574,1096,1097],{},[275,1098,1015],{},[574,1100,1101],{},[275,1102,1020],{},[574,1104,982],{},[574,1106,1107],{},"server-side",[298,1109],{},[301,1111,1113],{"id":1112},"implementing-a-custom-provider","Implementing a custom provider",[271,1115,1116,1117,1119],{},"Implement ",[275,1118,212],{}," directly for any strategy Authyra doesn't ship:",[306,1121,1123],{"className":308,"code":1122,"language":310,"meta":311,"style":311},"class MyApiProvider implements AuthProvider {\n  @override\n  String get id => 'my-api';\n\n  @override\n  AuthProviderType get type => AuthProviderType.credentials;\n\n  @override\n  bool get supportsRefresh => true;\n\n  @override\n  bool get supportsSignOut => true;\n\n  @override\n  Future\u003CAuthSignInResult?> signIn({Map\u003CString, dynamic>? params}) async {\n    final res = await myApi.post('/auth/login', body: params);\n    if (res.statusCode == 401) return null;  // wrong credentials\n    if (res.statusCode != 200) throw AuthenticationFailedException(\n      'Login failed: HTTP ${res.statusCode}',\n      providerName: id,\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  @override\n  Future\u003CAuthTokenResult?> refreshToken(String refreshToken) async {\n    final res = await myApi.post('/auth/refresh',\n        body: {'refreshToken': refreshToken});\n    if (res.statusCode != 200) return null;\n    return AuthTokenResult(\n      accessToken: res.data['accessToken'],\n      expiresAt:   DateTime.parse(res.data['expiresAt']),\n      // refreshToken omitted → client keeps the existing one\n    );\n  }\n\n  @override\n  Future\u003Cvoid> signOut({String? userId}) async {\n    // Fire-and-forget — never throw here\n    await myApi.post('/auth/logout').catchError((_) {});\n  }\n}\n",[275,1124,1125,1139,1144,1161,1165,1169,1187,1191,1195,1208,1212,1216,1229,1234,1239,1275,1315,1348,1376,1403,1415,1423,1433,1445,1469,1491,1513,1521,1542,1563,1594,1601,1607,1612,1617,1640,1664,1684,1705,1714,1733,1759,1765,1772,1777,1782,1787,1813,1819,1849,1854],{"__ignoreMap":311},[315,1126,1127,1129,1132,1135,1137],{"class":317,"line":318},[315,1128,794],{"class":321},[315,1130,1131],{"class":328}," MyApiProvider",[315,1133,1134],{"class":321}," implements",[315,1136,329],{"class":328},[315,1138,333],{"class":332},[315,1140,1141],{"class":317,"line":336},[315,1142,1143],{"class":489},"  @override\n",[315,1145,1146,1148,1150,1153,1155,1159],{"class":317,"line":355},[315,1147,339],{"class":328},[315,1149,342],{"class":321},[315,1151,1152],{"class":332}," id ",[315,1154,365],{"class":321},[315,1156,1158],{"class":1157},"sfazB"," 'my-api'",[315,1160,397],{"class":321},[315,1162,1163],{"class":317,"line":375},[315,1164,434],{"emptyLinePlaceholder":433},[315,1166,1167],{"class":317,"line":400},[315,1168,1143],{"class":489},[315,1170,1171,1173,1175,1177,1179,1181,1183,1185],{"class":317,"line":416},[315,1172,378],{"class":328},[315,1174,342],{"class":321},[315,1176,383],{"class":332},[315,1178,365],{"class":321},[315,1180,388],{"class":328},[315,1182,391],{"class":321},[315,1184,979],{"class":332},[315,1186,397],{"class":321},[315,1188,1189],{"class":317,"line":430},[315,1190,434],{"emptyLinePlaceholder":433},[315,1192,1193],{"class":317,"line":437},[315,1194,1143],{"class":489},[315,1196,1197,1199,1201,1203,1205],{"class":317,"line":482},[315,1198,403],{"class":328},[315,1200,342],{"class":321},[315,1202,408],{"class":332},[315,1204,365],{"class":321},[315,1206,1207],{"class":321}," true;\n",[315,1209,1210],{"class":317,"line":514},[315,1211,434],{"emptyLinePlaceholder":433},[315,1213,1214],{"class":317,"line":545},[315,1215,1143],{"class":489},[315,1217,1219,1221,1223,1225,1227],{"class":317,"line":1218},12,[315,1220,403],{"class":328},[315,1222,342],{"class":321},[315,1224,423],{"class":332},[315,1226,365],{"class":321},[315,1228,1207],{"class":321},[315,1230,1232],{"class":317,"line":1231},13,[315,1233,434],{"emptyLinePlaceholder":433},[315,1235,1237],{"class":317,"line":1236},14,[315,1238,1143],{"class":489},[315,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258,1260,1262,1264,1266,1268,1271,1273],{"class":317,"line":1241},15,[315,1243,440],{"class":328},[315,1245,443],{"class":332},[315,1247,446],{"class":328},[315,1249,449],{"class":332},[315,1251,287],{"class":452},[315,1253,455],{"class":332},[315,1255,458],{"class":328},[315,1257,443],{"class":332},[315,1259,463],{"class":328},[315,1261,288],{"class":332},[315,1263,468],{"class":328},[315,1265,471],{"class":332},[315,1267,474],{"class":321},[315,1269,1270],{"class":332}," params}) ",[315,1272,508],{"class":507},[315,1274,333],{"class":332},[315,1276,1278,1281,1284,1287,1290,1293,1295,1298,1300,1303,1305,1308,1310,1313],{"class":317,"line":1277},16,[315,1279,1280],{"class":489},"    final",[315,1282,1283],{"class":332}," res ",[315,1285,1286],{"class":321},"=",[315,1288,1289],{"class":507}," await",[315,1291,1292],{"class":332}," myApi",[315,1294,391],{"class":321},[315,1296,1297],{"class":452},"post",[315,1299,529],{"class":332},[315,1301,1302],{"class":1157},"'/auth/login'",[315,1304,721],{"class":321},[315,1306,1307],{"class":332}," body",[315,1309,699],{"class":321},[315,1311,1312],{"class":332}," params)",[315,1314,397],{"class":321},[315,1316,1318,1321,1324,1326,1329,1332,1336,1339,1342,1345],{"class":317,"line":1317},17,[315,1319,1320],{"class":507},"    if",[315,1322,1323],{"class":332}," (res",[315,1325,391],{"class":321},[315,1327,1328],{"class":332},"statusCode ",[315,1330,1331],{"class":321},"==",[315,1333,1335],{"class":1334},"sbssI"," 401",[315,1337,1338],{"class":332},") ",[315,1340,1341],{"class":507},"return",[315,1343,1344],{"class":321}," null;",[315,1346,1347],{"class":351},"  // wrong credentials\n",[315,1349,1351,1353,1355,1357,1359,1362,1365,1367,1370,1373],{"class":317,"line":1350},18,[315,1352,1320],{"class":507},[315,1354,1323],{"class":332},[315,1356,391],{"class":321},[315,1358,1328],{"class":332},[315,1360,1361],{"class":321},"!=",[315,1363,1364],{"class":1334}," 200",[315,1366,1338],{"class":332},[315,1368,1369],{"class":507},"throw",[315,1371,1372],{"class":328}," AuthenticationFailedException",[315,1374,1375],{"class":332},"(\n",[315,1377,1379,1382,1385,1389,1391,1394,1397,1400],{"class":317,"line":1378},19,[315,1380,1381],{"class":1157},"      'Login failed: HTTP ",[315,1383,1384],{"class":332},"${",[315,1386,1388],{"class":1387},"sHdIc","res",[315,1390,391],{"class":332},[315,1392,1393],{"class":1387},"statusCode",[315,1395,1396],{"class":332},"}",[315,1398,1399],{"class":1157},"'",[315,1401,1402],{"class":321},",\n",[315,1404,1406,1409,1411,1413],{"class":317,"line":1405},20,[315,1407,1408],{"class":332},"      providerName",[315,1410,699],{"class":321},[315,1412,345],{"class":332},[315,1414,1402],{"class":321},[315,1416,1418,1421],{"class":317,"line":1417},21,[315,1419,1420],{"class":332},"    )",[315,1422,397],{"class":321},[315,1424,1426,1429,1431],{"class":317,"line":1425},22,[315,1427,1428],{"class":507},"    return",[315,1430,797],{"class":328},[315,1432,1375],{"class":332},[315,1434,1436,1439,1441,1443],{"class":317,"line":1435},23,[315,1437,1438],{"class":332},"      user",[315,1440,699],{"class":321},[315,1442,807],{"class":328},[315,1444,1375],{"class":332},[315,1446,1448,1451,1453,1456,1458,1461,1464,1467],{"class":317,"line":1447},24,[315,1449,1450],{"class":332},"        id",[315,1452,699],{"class":321},[315,1454,1455],{"class":332},"    res",[315,1457,391],{"class":321},[315,1459,1460],{"class":332},"data[",[315,1462,1463],{"class":1157},"'id'",[315,1465,1466],{"class":332},"]",[315,1468,1402],{"class":321},[315,1470,1472,1475,1477,1480,1482,1484,1487,1489],{"class":317,"line":1471},25,[315,1473,1474],{"class":332},"        email",[315,1476,699],{"class":321},[315,1478,1479],{"class":332}," res",[315,1481,391],{"class":321},[315,1483,1460],{"class":332},[315,1485,1486],{"class":1157},"'email'",[315,1488,1466],{"class":332},[315,1490,1402],{"class":321},[315,1492,1494,1497,1499,1502,1504,1506,1509,1511],{"class":317,"line":1493},26,[315,1495,1496],{"class":332},"        name",[315,1498,699],{"class":321},[315,1500,1501],{"class":332},"  res",[315,1503,391],{"class":321},[315,1505,1460],{"class":332},[315,1507,1508],{"class":1157},"'name'",[315,1510,1466],{"class":332},[315,1512,1402],{"class":321},[315,1514,1516,1519],{"class":317,"line":1515},27,[315,1517,1518],{"class":332},"      )",[315,1520,1402],{"class":321},[315,1522,1524,1527,1529,1531,1533,1535,1538,1540],{"class":317,"line":1523},28,[315,1525,1526],{"class":332},"      accessToken",[315,1528,699],{"class":321},[315,1530,1501],{"class":332},[315,1532,391],{"class":321},[315,1534,1460],{"class":332},[315,1536,1537],{"class":1157},"'accessToken'",[315,1539,1466],{"class":332},[315,1541,1402],{"class":321},[315,1543,1545,1548,1550,1552,1554,1556,1559,1561],{"class":317,"line":1544},29,[315,1546,1547],{"class":332},"      refreshToken",[315,1549,699],{"class":321},[315,1551,1479],{"class":332},[315,1553,391],{"class":321},[315,1555,1460],{"class":332},[315,1557,1558],{"class":1157},"'refreshToken'",[315,1560,1466],{"class":332},[315,1562,1402],{"class":321},[315,1564,1566,1569,1571,1574,1576,1579,1582,1584,1586,1589,1592],{"class":317,"line":1565},30,[315,1567,1568],{"class":332},"      expiresAt",[315,1570,699],{"class":321},[315,1572,1573],{"class":328},"    DateTime",[315,1575,391],{"class":321},[315,1577,1578],{"class":452},"parse",[315,1580,1581],{"class":332},"(res",[315,1583,391],{"class":321},[315,1585,1460],{"class":332},[315,1587,1588],{"class":1157},"'expiresAt'",[315,1590,1591],{"class":332},"])",[315,1593,1402],{"class":321},[315,1595,1597,1599],{"class":317,"line":1596},31,[315,1598,1420],{"class":332},[315,1600,397],{"class":321},[315,1602,1604],{"class":317,"line":1603},32,[315,1605,1606],{"class":332},"  }\n",[315,1608,1610],{"class":317,"line":1609},33,[315,1611,434],{"emptyLinePlaceholder":433},[315,1613,1615],{"class":317,"line":1614},34,[315,1616,1143],{"class":489},[315,1618,1620,1622,1624,1626,1628,1630,1632,1634,1636,1638],{"class":317,"line":1619},35,[315,1621,440],{"class":328},[315,1623,443],{"class":332},[315,1625,521],{"class":328},[315,1627,449],{"class":332},[315,1629,295],{"class":452},[315,1631,529],{"class":332},[315,1633,463],{"class":328},[315,1635,534],{"class":332},[315,1637,508],{"class":507},[315,1639,333],{"class":332},[315,1641,1643,1645,1647,1649,1651,1653,1655,1657,1659,1662],{"class":317,"line":1642},36,[315,1644,1280],{"class":489},[315,1646,1283],{"class":332},[315,1648,1286],{"class":321},[315,1650,1289],{"class":507},[315,1652,1292],{"class":332},[315,1654,391],{"class":321},[315,1656,1297],{"class":452},[315,1658,529],{"class":332},[315,1660,1661],{"class":1157},"'/auth/refresh'",[315,1663,1402],{"class":321},[315,1665,1667,1670,1672,1675,1677,1679,1682],{"class":317,"line":1666},37,[315,1668,1669],{"class":332},"        body",[315,1671,699],{"class":321},[315,1673,1674],{"class":332}," {",[315,1676,1558],{"class":1157},[315,1678,699],{"class":321},[315,1680,1681],{"class":332}," refreshToken})",[315,1683,397],{"class":321},[315,1685,1687,1689,1691,1693,1695,1697,1699,1701,1703],{"class":317,"line":1686},38,[315,1688,1320],{"class":507},[315,1690,1323],{"class":332},[315,1692,391],{"class":321},[315,1694,1328],{"class":332},[315,1696,1361],{"class":321},[315,1698,1364],{"class":1334},[315,1700,1338],{"class":332},[315,1702,1341],{"class":507},[315,1704,542],{"class":321},[315,1706,1708,1710,1712],{"class":317,"line":1707},39,[315,1709,1428],{"class":507},[315,1711,890],{"class":328},[315,1713,1375],{"class":332},[315,1715,1717,1719,1721,1723,1725,1727,1729,1731],{"class":317,"line":1716},40,[315,1718,1526],{"class":332},[315,1720,699],{"class":321},[315,1722,1479],{"class":332},[315,1724,391],{"class":321},[315,1726,1460],{"class":332},[315,1728,1537],{"class":1157},[315,1730,1466],{"class":332},[315,1732,1402],{"class":321},[315,1734,1736,1738,1740,1743,1745,1747,1749,1751,1753,1755,1757],{"class":317,"line":1735},41,[315,1737,1568],{"class":332},[315,1739,699],{"class":321},[315,1741,1742],{"class":328},"   DateTime",[315,1744,391],{"class":321},[315,1746,1578],{"class":452},[315,1748,1581],{"class":332},[315,1750,391],{"class":321},[315,1752,1460],{"class":332},[315,1754,1588],{"class":1157},[315,1756,1591],{"class":332},[315,1758,1402],{"class":321},[315,1760,1762],{"class":317,"line":1761},42,[315,1763,1764],{"class":351},"      // refreshToken omitted → client keeps the existing one\n",[315,1766,1768,1770],{"class":317,"line":1767},43,[315,1769,1420],{"class":332},[315,1771,397],{"class":321},[315,1773,1775],{"class":317,"line":1774},44,[315,1776,1606],{"class":332},[315,1778,1780],{"class":317,"line":1779},45,[315,1781,434],{"emptyLinePlaceholder":433},[315,1783,1785],{"class":317,"line":1784},46,[315,1786,1143],{"class":489},[315,1788,1790,1792,1794,1796,1799,1801,1803,1805,1807,1809,1811],{"class":317,"line":1789},47,[315,1791,440],{"class":328},[315,1793,443],{"class":332},[315,1795,490],{"class":489},[315,1797,1798],{"class":332},"> ",[315,1800,291],{"class":452},[315,1802,455],{"class":332},[315,1804,463],{"class":328},[315,1806,474],{"class":321},[315,1808,504],{"class":332},[315,1810,508],{"class":507},[315,1812,333],{"class":332},[315,1814,1816],{"class":317,"line":1815},48,[315,1817,1818],{"class":351},"    // Fire-and-forget — never throw here\n",[315,1820,1822,1825,1827,1829,1831,1833,1836,1839,1841,1844,1847],{"class":317,"line":1821},49,[315,1823,1824],{"class":507},"    await",[315,1826,1292],{"class":332},[315,1828,391],{"class":321},[315,1830,1297],{"class":452},[315,1832,529],{"class":332},[315,1834,1835],{"class":1157},"'/auth/logout'",[315,1837,1838],{"class":332},")",[315,1840,391],{"class":321},[315,1842,1843],{"class":452},"catchError",[315,1845,1846],{"class":332},"((_) {})",[315,1848,397],{"class":321},[315,1850,1852],{"class":317,"line":1851},50,[315,1853,1606],{"class":332},[315,1855,1857],{"class":317,"line":1856},51,[315,1858,548],{"class":332},[271,1860,1861,1862,1864],{},"Register it in ",[275,1863,199],{}," like any other provider:",[306,1866,1868],{"className":308,"code":1867,"language":310,"meta":311,"style":311},"AuthyraClient(\n  providers: [MyApiProvider()],\n  storage: SecureAuthStorage(),\n)\n",[275,1869,1870,1876,1894,1909],{"__ignoreMap":311},[315,1871,1872,1874],{"class":317,"line":318},[315,1873,199],{"class":328},[315,1875,1375],{"class":332},[315,1877,1878,1881,1883,1886,1889,1892],{"class":317,"line":336},[315,1879,1880],{"class":332},"  providers",[315,1882,699],{"class":321},[315,1884,1885],{"class":332}," [",[315,1887,1888],{"class":328},"MyApiProvider",[315,1890,1891],{"class":332},"()]",[315,1893,1402],{"class":321},[315,1895,1896,1899,1901,1904,1907],{"class":317,"line":355},[315,1897,1898],{"class":332},"  storage",[315,1900,699],{"class":321},[315,1902,1903],{"class":328}," SecureAuthStorage",[315,1905,1906],{"class":332},"()",[315,1908,1402],{"class":321},[315,1910,1911],{"class":317,"line":375},[315,1912,1913],{"class":332},")\n",[298,1915],{},[301,1917,1919],{"id":1918},"provider-design-rules","Provider design rules",[1921,1922,1923,1934,1954,1966,1974],"ul",{},[1924,1925,1926,1930,1931,391],"li",{},[1927,1928,1929],"strong",{},"Stateless",": providers hold configuration, never session state. Session state lives in ",[275,1932,1933],{},"SessionManager",[1924,1935,1936,1941,1942,1944,1945,1947,1948,1950,1951,391],{},[1927,1937,1938,1939,656],{},"Return ",[275,1940,655],{},": ",[275,1943,199],{}," converts a ",[275,1946,655],{}," return from ",[275,1949,287],{}," into ",[275,1952,1953],{},"AuthenticationFailedException",[1924,1955,1956,1959,1960,1963,1964,391],{},[1927,1957,1958],{},"Throw for infrastructure errors",": network failures, CSRF mismatches, and invalid config should throw an ",[275,1961,1962],{},"AuthyraException"," subclass — not return ",[275,1965,655],{},[1924,1967,1968,1973],{},[1927,1969,1970,1972],{},[275,1971,291],{}," must never throw",": catch and log errors internally to avoid blocking local session cleanup.",[1924,1975,1976,1979,1980,1983,1984,1986,1987,1989],{},[1927,1977,1978],{},"Populate token fields when available",": leaving ",[275,1981,1982],{},"accessToken"," as ",[275,1985,655],{}," prevents ",[275,1988,869],{}," and silent refresh from working.",[298,1991],{},[301,1993,1995],{"id":1994},"see-also","See also",[1921,1997,1998,2004,2009,2014],{},[1924,1999,2000],{},[2001,2002,2003],"a",{"href":95},"Credentials Provider →",[1924,2005,2006],{},[2001,2007,2008],{"href":99},"OAuth2 Provider →",[1924,2010,2011],{},[2001,2012,2013],{"href":153},"Custom Provider guide →",[1924,2015,2016],{},[2001,2017,2018],{"href":56},"Architecture →",[2020,2021,2022],"style",{},"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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .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":311,"searchDepth":336,"depth":336,"links":2024},[2025,2026,2027,2031,2032,2033,2034],{"id":303,"depth":336,"text":304},{"id":689,"depth":336,"text":690},{"id":773,"depth":336,"text":774,"children":2028},[2029,2030],{"id":778,"depth":355,"text":446},{"id":873,"depth":355,"text":521},{"id":938,"depth":336,"text":939},{"id":1112,"depth":336,"text":1113},{"id":1918,"depth":336,"text":1919},{"id":1994,"depth":336,"text":1995},"The AuthProvider interface — strategy types, sign-in, sign-out, and token refresh.","md",null,{},{"icon":63},{"title":2041,"description":2042},"Providers | Authyra","Understand the AuthProvider interface — strategy types, result objects, and how to implement a custom provider.","43RQiz2EhTKTu4sEQ-4FgalMra0GLoe9b0V7h-wkeU4",[2045,2047],{"title":55,"path":56,"stem":57,"description":2046,"icon":58,"children":-1},"How the two packages, AuthyraClient, AuthyraInstance, and the provider/storage system fit together.",{"title":65,"path":66,"stem":67,"description":2048,"icon":68,"children":-1},"AuthSession lifecycle — fields, expiry helpers, token refresh, and multi-account support.",1782700506039]