TF-624 Implement logout oidc on browser
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -99,15 +99,11 @@ class AccountCacheClient extends HiveCacheClient<AccountCache> {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Box<AccountCache>> openBox() {
|
||||
return Future.sync(() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<AccountCache>(tableName);
|
||||
}
|
||||
return await Hive.openBox<AccountCache>(tableName);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
Future<Box<AccountCache>> openBox() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<AccountCache>(tableName);
|
||||
}
|
||||
return Hive.openBox<AccountCache>(tableName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -11,15 +11,11 @@ class EmailCacheClient extends HiveCacheClient<EmailCache> {
|
||||
String get tableName => 'EmailCache';
|
||||
|
||||
@override
|
||||
Future<Box<EmailCache>> openBox() {
|
||||
return Future.sync(() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<EmailCache>(tableName);
|
||||
}
|
||||
return await Hive.openBox<EmailCache>(tableName);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
Future<Box<EmailCache>> openBox() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<EmailCache>(tableName);
|
||||
}
|
||||
return Hive.openBox<EmailCache>(tableName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -9,15 +9,11 @@ class MailboxCacheClient extends HiveCacheClient<MailboxCache> {
|
||||
String get tableName => 'MailboxCache';
|
||||
|
||||
@override
|
||||
Future<Box<MailboxCache>> openBox() {
|
||||
return Future.sync(() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<MailboxCache>(tableName);
|
||||
}
|
||||
return await Hive.openBox<MailboxCache>(tableName);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
Future<Box<MailboxCache>> openBox() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<MailboxCache>(tableName);
|
||||
}
|
||||
return Hive.openBox<MailboxCache>(tableName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -88,15 +88,11 @@ class RecentSearchCacheClient extends HiveCacheClient<RecentSearchCache> {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Box<RecentSearchCache>> openBox() {
|
||||
return Future.sync(() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<RecentSearchCache>(tableName);
|
||||
}
|
||||
return await Hive.openBox<RecentSearchCache>(tableName);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
Future<Box<RecentSearchCache>> openBox() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<RecentSearchCache>(tableName);
|
||||
}
|
||||
return Hive.openBox<RecentSearchCache>(tableName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -9,15 +9,11 @@ class StateCacheClient extends HiveCacheClient<StateCache> {
|
||||
String get tableName => 'StateCache';
|
||||
|
||||
@override
|
||||
Future<Box<StateCache>> openBox() {
|
||||
return Future.sync(() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<StateCache>(tableName);
|
||||
}
|
||||
return await Hive.openBox<StateCache>(tableName);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
Future<Box<StateCache>> openBox() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<StateCache>(tableName);
|
||||
}
|
||||
return Hive.openBox<StateCache>(tableName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -97,15 +97,11 @@ class TokenOidcCacheClient extends HiveCacheClient<TokenOidcCache> {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Box<TokenOidcCache>> openBox() {
|
||||
return Future.sync(() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<TokenOidcCache>(tableName);
|
||||
}
|
||||
return await Hive.openBox<TokenOidcCache>(tableName);
|
||||
}).catchError((error) {
|
||||
throw error;
|
||||
});
|
||||
Future<Box<TokenOidcCache>> openBox() async {
|
||||
if (Hive.isBoxOpen(tableName)) {
|
||||
return Hive.box<TokenOidcCache>(tableName);
|
||||
}
|
||||
return Hive.openBox<TokenOidcCache>(tableName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -47,12 +47,12 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TokenOIDC> getStoredTokenOIDC(String tokenIdHash) async {
|
||||
Future<TokenOIDC> getStoredTokenOIDC(String tokenIdHash) {
|
||||
return _tokenOidcCacheManager.getTokenOidc(tokenIdHash);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> persistTokenOIDC(TokenOIDC tokenOidc) async {
|
||||
Future<void> persistTokenOIDC(TokenOIDC tokenOidc) {
|
||||
return _tokenOidcCacheManager.persistOneTokenOidc(tokenOidc);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ class AuthenticationClientMobile implements AuthenticationClientBase {
|
||||
Future<bool> 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}');
|
||||
|
||||
+7
-2
@@ -44,8 +44,13 @@ class AuthenticationClientWeb implements AuthenticationClientBase {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> logoutOidc(TokenId tokenId, OIDCConfiguration config) {
|
||||
throw UnimplementedError();
|
||||
Future<bool> 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
|
||||
|
||||
@@ -21,7 +21,7 @@ class LogoutOidcInteractor {
|
||||
Stream<Either<Failure, Success>> 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');
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<script>
|
||||
const AUTH_RESPONSE_KEY = "auth_info";
|
||||
const CODE_VERIFIER_KEY = "auth_code_verifier";
|
||||
window.onload = function () {
|
||||
localStorage.removeItem(AUTH_RESPONSE_KEY);
|
||||
localStorage.removeItem(CODE_VERIFIER_KEY);
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
if (params.has('redirect_uri')) {
|
||||
const redirect = params.get('redirect_uri');
|
||||
window.location.replace(redirect);
|
||||
} else {
|
||||
window.location.assign("/");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user