diff --git a/lib/features/base/reloadable/reloadable_controller.dart b/lib/features/base/reloadable/reloadable_controller.dart index 358efe021..28e5da4c7 100644 --- a/lib/features/base/reloadable/reloadable_controller.dart +++ b/lib/features/base/reloadable/reloadable_controller.dart @@ -13,6 +13,8 @@ import 'package:tmail_ui_user/features/login/domain/state/get_credential_state.d import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_credential_interactor.dart'; +import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; +import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/log_out_oidc_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/features/session/domain/state/get_session_state.dart'; @@ -41,7 +43,7 @@ abstract class ReloadableController extends BaseController { viewState.value.fold( (failure) { if (failure is GetCredentialFailure) { - goToLogin(); + _goToLogin(); } else if (failure is GetSessionFailure) { _handleGetSessionFailure(); } else if (failure is LogoutOidcFailure) { @@ -71,8 +73,8 @@ abstract class ReloadableController extends BaseController { consumeState(_getCredentialInteractor.execute().asStream()); } - void goToLogin() { - pushAndPopAll(AppRoutes.LOGIN); + void _goToLogin({LoginArguments? arguments}) { + pushAndPopAll(AppRoutes.LOGIN, arguments: arguments); } void _setUpInterceptors(GetCredentialViewState credentialViewState) { @@ -92,13 +94,12 @@ abstract class ReloadableController extends BaseController { consumeState(_getSessionInteractor.execute().asStream()); } - void _handleGetSessionFailure() { - _deleteCredentialAction(); - goToLogin(); - } - - void _deleteCredentialAction() async { - await _deleteCredentialInteractor.execute(); + void _handleGetSessionFailure() async { + await Future.wait([ + _deleteCredentialInteractor.execute(), + _cachingManager.clearAll(), + ]); + _goToLogin(); } void _handleGetSessionSuccess(GetSessionSuccess success) { @@ -118,7 +119,8 @@ abstract class ReloadableController extends BaseController { ]); _authorizationInterceptors.clear(); - goToLogin(); + await HiveCacheConfig().closeHive(); + _goToLogin(); } } @@ -131,6 +133,7 @@ abstract class ReloadableController extends BaseController { ]); _authorizationInterceptors.clear(); - goToLogin(); + await HiveCacheConfig().closeHive(); + _goToLogin(arguments: LoginArguments(LoginFormType.ssoForm)); } } \ No newline at end of file diff --git a/lib/features/caching/account_cache_client.dart b/lib/features/caching/account_cache_client.dart index 2630dae8e..4f3130eb1 100644 --- a/lib/features/caching/account_cache_client.dart +++ b/lib/features/caching/account_cache_client.dart @@ -99,15 +99,11 @@ class AccountCacheClient extends HiveCacheClient { } @override - Future> openBox() { - return Future.sync(() async { - if (Hive.isBoxOpen(tableName)) { - return Hive.box(tableName); - } - return await Hive.openBox(tableName); - }).catchError((error) { - throw error; - }); + Future> openBox() async { + if (Hive.isBoxOpen(tableName)) { + return Hive.box(tableName); + } + return Hive.openBox(tableName); } @override diff --git a/lib/features/caching/email_cache_client.dart b/lib/features/caching/email_cache_client.dart index 3de49285a..c55ba18e4 100644 --- a/lib/features/caching/email_cache_client.dart +++ b/lib/features/caching/email_cache_client.dart @@ -11,15 +11,11 @@ class EmailCacheClient extends HiveCacheClient { String get tableName => 'EmailCache'; @override - Future> openBox() { - return Future.sync(() async { - if (Hive.isBoxOpen(tableName)) { - return Hive.box(tableName); - } - return await Hive.openBox(tableName); - }).catchError((error) { - throw error; - }); + Future> openBox() async { + if (Hive.isBoxOpen(tableName)) { + return Hive.box(tableName); + } + return Hive.openBox(tableName); } @override diff --git a/lib/features/caching/mailbox_cache_client.dart b/lib/features/caching/mailbox_cache_client.dart index b4fe02ff7..92ee19a74 100644 --- a/lib/features/caching/mailbox_cache_client.dart +++ b/lib/features/caching/mailbox_cache_client.dart @@ -9,15 +9,11 @@ class MailboxCacheClient extends HiveCacheClient { String get tableName => 'MailboxCache'; @override - Future> openBox() { - return Future.sync(() async { - if (Hive.isBoxOpen(tableName)) { - return Hive.box(tableName); - } - return await Hive.openBox(tableName); - }).catchError((error) { - throw error; - }); + Future> openBox() async { + if (Hive.isBoxOpen(tableName)) { + return Hive.box(tableName); + } + return Hive.openBox(tableName); } @override diff --git a/lib/features/caching/recent_search_cache_client.dart b/lib/features/caching/recent_search_cache_client.dart index 150375967..d73a29496 100644 --- a/lib/features/caching/recent_search_cache_client.dart +++ b/lib/features/caching/recent_search_cache_client.dart @@ -88,15 +88,11 @@ class RecentSearchCacheClient extends HiveCacheClient { } @override - Future> openBox() { - return Future.sync(() async { - if (Hive.isBoxOpen(tableName)) { - return Hive.box(tableName); - } - return await Hive.openBox(tableName); - }).catchError((error) { - throw error; - }); + Future> openBox() async { + if (Hive.isBoxOpen(tableName)) { + return Hive.box(tableName); + } + return Hive.openBox(tableName); } @override diff --git a/lib/features/caching/state_cache_client.dart b/lib/features/caching/state_cache_client.dart index 1ae9168e5..cfd1e6dee 100644 --- a/lib/features/caching/state_cache_client.dart +++ b/lib/features/caching/state_cache_client.dart @@ -9,15 +9,11 @@ class StateCacheClient extends HiveCacheClient { String get tableName => 'StateCache'; @override - Future> openBox() { - return Future.sync(() async { - if (Hive.isBoxOpen(tableName)) { - return Hive.box(tableName); - } - return await Hive.openBox(tableName); - }).catchError((error) { - throw error; - }); + Future> openBox() async { + if (Hive.isBoxOpen(tableName)) { + return Hive.box(tableName); + } + return Hive.openBox(tableName); } @override diff --git a/lib/features/caching/token_oidc_cache_client.dart b/lib/features/caching/token_oidc_cache_client.dart index f7ed44500..41120defb 100644 --- a/lib/features/caching/token_oidc_cache_client.dart +++ b/lib/features/caching/token_oidc_cache_client.dart @@ -97,15 +97,11 @@ class TokenOidcCacheClient extends HiveCacheClient { } @override - Future> openBox() { - return Future.sync(() async { - if (Hive.isBoxOpen(tableName)) { - return Hive.box(tableName); - } - return await Hive.openBox(tableName); - }).catchError((error) { - throw error; - }); + Future> openBox() async { + if (Hive.isBoxOpen(tableName)) { + return Hive.box(tableName); + } + return Hive.openBox(tableName); } @override diff --git a/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart b/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart index 3347cc0d2..d5f3763f0 100644 --- a/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart +++ b/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart @@ -47,12 +47,12 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { } @override - Future getStoredTokenOIDC(String tokenIdHash) async { + Future getStoredTokenOIDC(String tokenIdHash) { return _tokenOidcCacheManager.getTokenOidc(tokenIdHash); } @override - Future persistTokenOIDC(TokenOIDC tokenOidc) async { + Future persistTokenOIDC(TokenOIDC tokenOidc) { return _tokenOidcCacheManager.persistOneTokenOidc(tokenOidc); } diff --git a/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart b/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart index 36bc728d2..b9e6f5327 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart @@ -45,7 +45,7 @@ class AuthenticationClientMobile implements AuthenticationClientBase { Future logoutOidc(TokenId tokenId, OIDCConfiguration config) async { final endSession = await _appAuth.endSession(EndSessionRequest( idTokenHint: tokenId.uuid, - postLogoutRedirectUrl: config.redirectUrl, + postLogoutRedirectUrl: config.logoutRedirectUrl, discoveryUrl: config.discoveryUrl )); log('AuthenticationClientMobile::logoutOidc(): ${endSession?.state}'); diff --git a/lib/features/login/data/network/authentication_client/authentication_client_web.dart b/lib/features/login/data/network/authentication_client/authentication_client_web.dart index c5e543c7c..c50b0455e 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_web.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_web.dart @@ -44,8 +44,13 @@ class AuthenticationClientWeb implements AuthenticationClientBase { } @override - Future logoutOidc(TokenId tokenId, OIDCConfiguration config) { - throw UnimplementedError(); + Future logoutOidc(TokenId tokenId, OIDCConfiguration config) async { + final endSession = await _appAuthWeb.endSession(EndSessionRequest( + idTokenHint: tokenId.uuid, + postLogoutRedirectUrl: config.logoutRedirectUrl, + discoveryUrl: config.discoveryUrl + )); + return endSession != null; } @override diff --git a/lib/features/manage_account/domain/usecases/log_out_oidc_interactor.dart b/lib/features/manage_account/domain/usecases/log_out_oidc_interactor.dart index 8425604de..9c9c413e9 100644 --- a/lib/features/manage_account/domain/usecases/log_out_oidc_interactor.dart +++ b/lib/features/manage_account/domain/usecases/log_out_oidc_interactor.dart @@ -21,7 +21,7 @@ class LogoutOidcInteractor { Stream> execute() async* { try { final currentAccount = await _accountRepository.getCurrentAccount(); - + log('LogoutOidcInteractor::execute(): currentAccount: $currentAccount'); if (currentAccount.authenticationType == AuthenticationType.oidc) { final result = await Future.wait([ _authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id), @@ -29,6 +29,8 @@ class LogoutOidcInteractor { ]).then((result) async { final tokenOidc = result.first as TokenOIDC; final oidcConfig = result.last as OIDCConfiguration; + log('LogoutOidcInteractor::execute(): tokenOidc: ${tokenOidc.tokenId.uuid}'); + log('LogoutOidcInteractor::execute(): oidcConfig: $oidcConfig'); return await _authenticationOIDCRepository.logout(tokenOidc.tokenId, oidcConfig); }); log('LogoutOidcInteractor::execute(): statusSuccess: $result'); diff --git a/model/lib/oidc/oidc_configuration.dart b/model/lib/oidc/oidc_configuration.dart index ac9be95fb..552a405bc 100644 --- a/model/lib/oidc/oidc_configuration.dart +++ b/model/lib/oidc/oidc_configuration.dart @@ -5,6 +5,7 @@ import 'package:equatable/equatable.dart'; class OIDCConfiguration with EquatableMixin { static const redirectOidcMobile = 'teammail.mobile://oauthredirect'; static const redirectOidcWeb = 'http://localhost:3000/login-callback.html'; + static const logoutRedirectOidcWeb = 'http://localhost:3000/logout-callback.html'; static const wellKnownOpenId = '.well-known/openid-configuration'; final String authority; @@ -27,6 +28,8 @@ class OIDCConfiguration with EquatableMixin { String get redirectUrl => BuildUtils.isWeb ? redirectOidcWeb : redirectOidcMobile; + String get logoutRedirectUrl => BuildUtils.isWeb ? logoutRedirectOidcWeb : redirectOidcMobile; + String get clientIdHash => clientId.hashCode.toString(); @override diff --git a/web/logout-callback.html b/web/logout-callback.html new file mode 100644 index 000000000..9c902ba9b --- /dev/null +++ b/web/logout-callback.html @@ -0,0 +1,25 @@ + + + + + + + + + + + \ No newline at end of file