diff --git a/lib/features/login/data/local/oidc_configuration_cache_manager.dart b/lib/features/login/data/local/oidc_configuration_cache_manager.dart index 4034cc542..a8590d42b 100644 --- a/lib/features/login/data/local/oidc_configuration_cache_manager.dart +++ b/lib/features/login/data/local/oidc_configuration_cache_manager.dart @@ -16,7 +16,7 @@ class OidcConfigurationCacheManager { } else { return OIDCConfiguration( authority: authority, - clientId: OIDCConstant.mobileOidcClientId, + clientId: OIDCConstant.clientId, scopes: OIDCConstant.oidcScope); } } 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 4ef1b3606..c5e543c7c 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 @@ -1,7 +1,9 @@ import 'package:core/utils/app_logger.dart'; import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/login/data/extensions/authentication_token_extension.dart'; import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.dart'; +import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; import 'package:universal_html/html.dart' as html; import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart'; import 'package:flutter_appauth_platform_interface/flutter_appauth_platform_interface.dart'; @@ -20,7 +22,25 @@ class AuthenticationClientWeb implements AuthenticationClientBase { @override Future getTokenOIDC(String clientId, String redirectUrl, String discoveryUrl, List scopes) async { - throw UnimplementedError(); + final authorizationTokenResponse = await _appAuthWeb.authorizeAndExchangeCode(AuthorizationTokenRequest( + clientId, + redirectUrl, + discoveryUrl: discoveryUrl, + scopes: scopes, + preferEphemeralSession: true)); + + log('AuthClientMobile::getTokenOIDC(): token: ${authorizationTokenResponse?.accessToken}'); + + if (authorizationTokenResponse != null) { + final tokenOIDC = authorizationTokenResponse.toTokenOIDC(); + if (tokenOIDC.isTokenValid()) { + return tokenOIDC; + } else { + throw AccessTokenInvalidException(); + } + } else { + throw NotFoundAccessTokenException(); + } } @override diff --git a/lib/features/login/domain/state/get_stored_oidc_configuration_state.dart b/lib/features/login/domain/state/get_stored_oidc_configuration_state.dart new file mode 100644 index 000000000..e0a743746 --- /dev/null +++ b/lib/features/login/domain/state/get_stored_oidc_configuration_state.dart @@ -0,0 +1,21 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:model/oidc/oidc_configuration.dart'; + +class GetStoredOidcConfigurationSuccess extends UIState { + final OIDCConfiguration oidcConfiguration; + + GetStoredOidcConfigurationSuccess(this.oidcConfiguration); + + @override + List get props => [oidcConfiguration]; +} + +class GetStoredOidcConfigurationFailure extends FeatureFailure { + final dynamic exception; + + GetStoredOidcConfigurationFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/login/domain/usecases/get_oidc_configuration_interactor.dart b/lib/features/login/domain/usecases/get_oidc_configuration_interactor.dart index c2eccf810..a1995110f 100644 --- a/lib/features/login/domain/usecases/get_oidc_configuration_interactor.dart +++ b/lib/features/login/domain/usecases/get_oidc_configuration_interactor.dart @@ -13,6 +13,7 @@ class GetOIDCConfigurationInteractor { try { final oidcConfiguration = await _oidcRepository.getOIDCConfiguration(oidcResponse); log('GetOIDCConfigurationInteractor::execute(): oidcConfiguration: $oidcConfiguration'); + await _oidcRepository.persistAuthorityOidc(oidcConfiguration.authority); return Right(GetOIDCConfigurationSuccess(oidcConfiguration)); } catch (e) { log('GetOIDCConfigurationInteractor::execute(): ERROR: $e'); diff --git a/lib/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart b/lib/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart new file mode 100644 index 000000000..7500bf44b --- /dev/null +++ b/lib/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart @@ -0,0 +1,23 @@ +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:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; +import 'package:tmail_ui_user/features/login/domain/state/get_stored_oidc_configuration_state.dart'; + +class GetStoredOidcConfigurationInteractor { + final AuthenticationOIDCRepository _authenticationOIDCRepository; + + GetStoredOidcConfigurationInteractor(this._authenticationOIDCRepository); + + Future> execute() async { + try { + final config = await _authenticationOIDCRepository.getStoredOidcConfiguration(); + log('GetStoredOidcConfigurationInteractor::execute(): oidcConfiguration: $config'); + return Right(GetStoredOidcConfigurationSuccess(config)); + } catch (e) { + log('GetStoredOidcConfigurationInteractor::execute(): $e'); + return Left(GetStoredOidcConfigurationFailure(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 893c23646..94c1edb75 100644 --- a/lib/features/login/presentation/login_bindings.dart +++ b/lib/features/login/presentation/login_bindings.dart @@ -27,6 +27,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/authentication_user 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_authentication_info_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; import 'package:tmail_ui_user/features/login/presentation/login_controller.dart'; @@ -43,6 +44,7 @@ class LoginBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), )); } @@ -91,6 +93,9 @@ class LoginBindings extends BaseBindings { Get.lazyPut(() => GetAuthenticationInfoInteractor( Get.find(), )); + Get.lazyPut(() => GetStoredOidcConfigurationInteractor( + Get.find(), + )); } @override diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart index 0fb54f064..13e2d4749 100644 --- a/lib/features/login/presentation/login_controller.dart +++ b/lib/features/login/presentation/login_controller.dart @@ -10,12 +10,14 @@ import 'package:tmail_ui_user/features/login/domain/state/authentication_user_st 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_authentication_info_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_stored_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_authentication_info_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; import 'package:tmail_ui_user/features/login/presentation/state/login_state.dart'; @@ -33,6 +35,7 @@ class LoginController extends GetxController { final GetTokenOIDCInteractor _getTokenOIDCInteractor; final AuthenticateOidcOnBrowserInteractor _authenticateOidcOnBrowserInteractor; final GetAuthenticationInfoInteractor _getAuthenticationInfoInteractor; + final GetStoredOidcConfigurationInteractor _getStoredOidcConfigurationInteractor; final TextEditingController urlInputController = TextEditingController(); @@ -45,6 +48,7 @@ class LoginController extends GetxController { this._getTokenOIDCInteractor, this._authenticateOidcOnBrowserInteractor, this._getAuthenticationInfoInteractor, + this._getStoredOidcConfigurationInteractor, ); var loginState = LoginState(Right(LoginInitAction())).obs; @@ -74,11 +78,11 @@ class LoginController extends GetxController { : null; @override - void onReady() { - super.onReady(); - if(BuildUtils.isWeb) { + void onInit() { + if (BuildUtils.isWeb) { _getAuthenticationInfo(); } + super.onInit(); } void _getAuthenticationInfo() async { @@ -87,10 +91,22 @@ class LoginController extends GetxController { (failure) => null, (success) { if (success is GetAuthenticationInfoSuccess) { + _getStoredOidcConfiguration(); } })); } + void _getStoredOidcConfiguration() async { + await _getStoredOidcConfigurationInteractor.execute() + .then((result) => result.fold( + (failure) => null, + (success) { + if (success is GetStoredOidcConfigurationSuccess) { + _getTokenOIDCAction(success.oidcConfiguration); + } + })); + } + void handleNextInUrlInputFormPress() { _checkOIDCIsAvailable(); }