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 b23b38332..9086092a9 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 @@ -90,6 +90,10 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { @override Future authenticateOidcOnBrowser(String clientId, String redirectUrl, String discoveryUrl, List scopes) { - throw UnimplementedError(); + return _authenticationClient.authenticateOidcOnBrowser( + clientId, + redirectUrl, + discoveryUrl, + scopes); } } \ No newline at end of file diff --git a/lib/features/login/data/network/authentication_client/authentication_client_base.dart b/lib/features/login/data/network/authentication_client/authentication_client_base.dart index f2a0aec12..6281b19df 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_base.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_base.dart @@ -6,7 +6,7 @@ import 'package:tmail_ui_user/features/login/data/network/authentication_client/ if (dart.library.html) 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_web.dart'; abstract class AuthenticationClientBase { - Future authenticateOidcOnBrowser( + Future authenticateOidcOnBrowser( String clientId, String redirectUrl, String discoveryUrl, 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 0f3724b95..c39f3e9bc 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 @@ -77,7 +77,7 @@ class AuthenticationClientMobile implements AuthenticationClientBase { } @override - Future authenticateOidcOnBrowser(String clientId, String redirectUrl, + Future authenticateOidcOnBrowser(String clientId, String redirectUrl, String discoveryUrl, List scopes) { return Future.value(null); } 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 463947b6c..eabfeb9fd 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 @@ -32,7 +32,7 @@ class AuthenticationClientWeb implements AuthenticationClientBase { } @override - Future authenticateOidcOnBrowser(String clientId, String redirectUrl, + Future authenticateOidcOnBrowser(String clientId, String redirectUrl, String discoveryUrl, List scopes) async { await _appAuthWeb.authorizeAndExchangeCode( AuthorizationTokenRequest( diff --git a/lib/features/login/domain/state/authenticate_oidc_on_browser_state.dart b/lib/features/login/domain/state/authenticate_oidc_on_browser_state.dart new file mode 100644 index 000000000..e1c6228ec --- /dev/null +++ b/lib/features/login/domain/state/authenticate_oidc_on_browser_state.dart @@ -0,0 +1,20 @@ + +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; + +class AuthenticateOidcOnBrowserSuccess extends UIState { + + AuthenticateOidcOnBrowserSuccess(); + + @override + List get props => []; +} + +class AuthenticateOidcOnBrowserFailure extends FeatureFailure { + final dynamic exception; + + AuthenticateOidcOnBrowserFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart b/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart new file mode 100644 index 000000000..5ef8caada --- /dev/null +++ b/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart @@ -0,0 +1,29 @@ + +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:core/utils/app_logger.dart'; +import 'package:dartz/dartz.dart'; +import 'package:model/oidc/oidc_configuration.dart'; +import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; +import 'package:tmail_ui_user/features/login/domain/state/authenticate_oidc_on_browser_state.dart'; + +class AuthenticateOidcOnBrowserInteractor { + + final AuthenticationOIDCRepository authenticationOIDCRepository; + + AuthenticateOidcOnBrowserInteractor(this.authenticationOIDCRepository); + + Future> execute(Uri baseUrl, OIDCConfiguration config) async { + try { + await authenticationOIDCRepository.authenticateOidcOnBrowser( + config.clientId, + config.redirectUrl, + config.discoveryUrl, + config.scopes); + return Right(AuthenticateOidcOnBrowserSuccess()); + } catch (e) { + logError('AuthenticateOidcOnBrowserInteractor::execute(): $e'); + return Left(AuthenticateOidcOnBrowserFailure(e)); + } + } +} \ No newline at end of file diff --git a/lib/features/login/presentation/login_bindings.dart b/lib/features/login/presentation/login_bindings.dart index 72280faa0..415f5521a 100644 --- a/lib/features/login/presentation/login_bindings.dart +++ b/lib/features/login/presentation/login_bindings.dart @@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/login/domain/repository/account_repositor import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/authentication_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/authentication_user_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/check_oidc_is_available_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; @@ -39,6 +40,7 @@ class LoginBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), )); } @@ -81,6 +83,9 @@ class LoginBindings extends BaseBindings { Get.find(), Get.find() )); + Get.lazyPut(() => AuthenticateOidcOnBrowserInteractor( + Get.find(), + )); } @override diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart index 5de171c0d..afceaa7e3 100644 --- a/lib/features/login/presentation/login_controller.dart +++ b/lib/features/login/presentation/login_controller.dart @@ -5,10 +5,12 @@ import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; +import 'package:tmail_ui_user/features/login/domain/state/authenticate_oidc_on_browser_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/authentication_user_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_token_oidc_state.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/authentication_user_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/check_oidc_is_available_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; @@ -27,6 +29,7 @@ class LoginController extends GetxController { final CheckOIDCIsAvailableInteractor _checkOIDCIsAvailableInteractor; final GetOIDCConfigurationInteractor _getOIDCConfigurationInteractor; final GetTokenOIDCInteractor _getTokenOIDCInteractor; + final AuthenticateOidcOnBrowserInteractor _authenticateOidcOnBrowserInteractor; final TextEditingController urlInputController = TextEditingController(); @@ -37,6 +40,7 @@ class LoginController extends GetxController { this._checkOIDCIsAvailableInteractor, this._getOIDCConfigurationInteractor, this._getTokenOIDCInteractor, + this._authenticateOidcOnBrowserInteractor, ); var loginState = LoginState(Right(LoginInitAction())).obs; @@ -171,7 +175,11 @@ class LoginController extends GetxController { void _getOIDCConfigurationSuccess(GetOIDCConfigurationSuccess success) { loginState.value = LoginState(Right(success)); - _getTokenOIDCAction(success.oidcConfiguration); + if (BuildUtils.isWeb) { + _authenticateOidcOnBrowserAction(success.oidcConfiguration); + } else { + _getTokenOIDCAction(success.oidcConfiguration); + } } void _getTokenOIDCAction(OIDCConfiguration config) async { @@ -201,6 +209,29 @@ class LoginController extends GetxController { } } + void _authenticateOidcOnBrowserAction(OIDCConfiguration config) async { + loginState.value = LoginState(Right(LoginLoadingAction())); + final baseUri = _parseUri(AppConfig.baseUrl); + if (baseUri != null) { + await _authenticateOidcOnBrowserInteractor.execute(baseUri, config) + .then((response) => response.fold( + (failure) { + if (failure is AuthenticateOidcOnBrowserFailure) { + loginState.value = LoginState(Left(failure)); + } else { + loginState.value = LoginState(Left(LoginCanNotAuthenticationSSOAction())); + } + }, + (success) { + if (success is! AuthenticateOidcOnBrowserSuccess) { + loginState.value = LoginState(Left(LoginCanNotAuthenticationSSOAction())); + } + })); + } else { + loginState.value = LoginState(Left(LoginCanNotAuthenticationSSOAction())); + } + } + void _getTokenOIDCSuccess(GetTokenOIDCSuccess success, OIDCConfiguration config) { log('LoginController::_getTokenOIDCSuccess(): ${success.tokenOIDC.toString()}'); loginState.value = LoginState(Right(success)); diff --git a/lib/features/login/presentation/state/login_state.dart b/lib/features/login/presentation/state/login_state.dart index bd2573889..502563db0 100644 --- a/lib/features/login/presentation/state/login_state.dart +++ b/lib/features/login/presentation/state/login_state.dart @@ -58,4 +58,9 @@ class LoginCanNotGetTokenAction extends Failure { class LoginSSONotAvailableAction extends Failure { @override List get props => []; +} + +class LoginCanNotAuthenticationSSOAction extends Failure { + @override + List get props => []; } \ No newline at end of file