@@ -240,6 +240,8 @@ class Authgear implements AuthgearHttpClientDelegate {
240240 Stream <SessionStateChangeEvent > get onSessionStateChange =>
241241 _sessionStateStreamController.stream;
242242
243+ Future <void >? _refreshAccessTokenTask;
244+
243245 String ? _accessToken;
244246 @override
245247 String ? get accessToken => _accessToken;
@@ -779,32 +781,47 @@ class Authgear implements AuthgearHttpClientDelegate {
779781
780782 @override
781783 Future <void > refreshAccessToken () async {
782- final refreshToken = _refreshToken;
783- if (refreshToken == null ) {
784- await _clearSession (SessionStateChangeReason .noToken);
785- return ;
786- }
784+ doRefreshAccessToken () async {
785+ final refreshToken = _refreshToken;
786+ if (refreshToken == null ) {
787+ await _clearSession (SessionStateChangeReason .noToken);
788+ return ;
789+ }
787790
788- String ? deviceSecret = await _sharedStorage.getDeviceSecret (name);
791+ String ? deviceSecret = await _sharedStorage.getDeviceSecret (name);
789792
790- final xDeviceInfo = await _getXDeviceInfo ();
791- final tokenRequest = OIDCTokenRequest (
792- grantType: GrantType .refreshToken,
793- clientID: clientID,
794- refreshToken: refreshToken,
795- xDeviceInfo: xDeviceInfo,
796- deviceSecret: deviceSecret,
797- );
793+ final xDeviceInfo = await _getXDeviceInfo ();
794+ final tokenRequest = OIDCTokenRequest (
795+ grantType: GrantType .refreshToken,
796+ clientID: clientID,
797+ refreshToken: refreshToken,
798+ xDeviceInfo: xDeviceInfo,
799+ deviceSecret: deviceSecret,
800+ );
801+ try {
802+ final tokenResponse = await _apiClient.sendTokenRequest (tokenRequest);
803+ await _persistTokenResponse (
804+ tokenResponse, SessionStateChangeReason .foundToken);
805+ } catch (e) {
806+ await _handleInvalidGrantException (e);
807+ if (e is OAuthException && e.error == "invalid_grant" ) {
808+ return ;
809+ }
810+ rethrow ;
811+ }
812+ }
813+
814+ if (_refreshAccessTokenTask != null ) {
815+ return await _refreshAccessTokenTask;
816+ }
817+ final newTask = doRefreshAccessToken ();
818+ _refreshAccessTokenTask = newTask;
798819 try {
799- final tokenResponse = await _apiClient.sendTokenRequest (tokenRequest);
800- await _persistTokenResponse (
801- tokenResponse, SessionStateChangeReason .foundToken);
802- } catch (e) {
803- await _handleInvalidGrantException (e);
804- if (e is OAuthException && e.error == "invalid_grant" ) {
805- return ;
820+ return await newTask;
821+ } finally {
822+ if (_refreshAccessTokenTask == newTask) {
823+ _refreshAccessTokenTask = null ;
806824 }
807- rethrow ;
808825 }
809826 }
810827
0 commit comments