diff --git a/packages/gotrue/lib/src/constants.dart b/packages/gotrue/lib/src/constants.dart index 3a2c3fa3..59cf63e1 100644 --- a/packages/gotrue/lib/src/constants.dart +++ b/packages/gotrue/lib/src/constants.dart @@ -56,3 +56,12 @@ enum OtpType { recovery, emailChange } + +///Determines which sessions should be logged out. +/// +///[global] means all sessions by this account will be signed out. +/// +///[local] means only this session will be signed out. +/// +///[others] means all other sessions except the current one will be signed out. When using others, there is no [AuthChangeEvent.signedOut] event fired on the current session! +enum SignOutScope { global, local, others } diff --git a/packages/gotrue/lib/src/gotrue_admin_api.dart b/packages/gotrue/lib/src/gotrue_admin_api.dart index 9951a757..b905da0a 100644 --- a/packages/gotrue/lib/src/gotrue_admin_api.dart +++ b/packages/gotrue/lib/src/gotrue_admin_api.dart @@ -1,4 +1,5 @@ import 'package:gotrue/gotrue.dart'; +import 'package:gotrue/src/constants.dart'; import 'package:gotrue/src/fetch.dart'; import 'package:gotrue/src/types/auth_response.dart'; import 'package:gotrue/src/types/fetch_options.dart'; @@ -28,9 +29,17 @@ class GoTrueAdminApi { } /// Removes a logged-in session. - Future signOut(String jwt) async { - final options = - GotrueRequestOptions(headers: _headers, noResolveJson: true, jwt: jwt); + Future signOut( + String jwt, { + SignOutScope scope = SignOutScope.global, + }) async { + final options = GotrueRequestOptions( + headers: _headers, + noResolveJson: true, + jwt: jwt, + query: {'scope': scope.name}, + ); + await _fetch.request( '$_url/logout', RequestMethodType.post, diff --git a/packages/gotrue/lib/src/gotrue_client.dart b/packages/gotrue/lib/src/gotrue_client.dart index 3b6543b5..a1014b09 100644 --- a/packages/gotrue/lib/src/gotrue_client.dart +++ b/packages/gotrue/lib/src/gotrue_client.dart @@ -618,13 +618,23 @@ class GoTrueClient { } /// Signs out the current user, if there is a logged in user. - Future signOut() async { + /// + /// If using [SignOutScope.others] scope, no [AuthChangeEvent.signedOut] event is fired! + Future signOut({ + SignOutScope scope = SignOutScope.global, + }) async { final accessToken = currentSession?.accessToken; - _removeSession(); - _notifyAllSubscribers(AuthChangeEvent.signedOut); + + if (scope != SignOutScope.others) { + _removeSession(); + await _asyncStorage?.removeItem( + key: '${Constants.defaultStorageKey}-code-verifier'); + _notifyAllSubscribers(AuthChangeEvent.signedOut); + } + if (accessToken != null) { try { - await admin.signOut(accessToken); + await admin.signOut(accessToken, scope: scope); } on AuthException catch (error) { // ignore 401s since an invalid or expired JWT should sign out the current session // ignore 404s since user might not exist anymore