generic-oauth2 icon indicating copy to clipboard operation
generic-oauth2 copied to clipboard

Feat: Logout Funtion & URL

Open loonix opened this issue 4 years ago • 24 comments

Describe the Feature

The current logout functionally only cleans any cached tokens but does not log out of the provider. For that to work we would have to provide a logout URL, which is not supported.

Platform(s) Support Requested

  • Android
  • iOS
  • Web

Describe Preferred Solution

Be able to logout completely from the app, it should clear the app cache and log the user out.

Describe Alternatives

None

Related Code

n/a

Additional Context

Reference: https://github.com/moberwasserlechner/capacitor-oauth2/issues/96

loonix avatar May 19 '20 07:05 loonix

Coded a workaround for azure b2c logout, while this feature is not completed:

//(...)
import { Plugins } from '@capacitor/core';
const { Browser } = Plugins;

//(...)
const urlLogout = 'https://XXXXXX.b2clogin.com/tfp/XXXXXX.onmicrosoft.com/b2c_1_sign_in/oauth2/v2.0/logout?client_id=XXXXX-XXXXX-XXXXX-XXXXX&response_type=token&redirect_uri=com.company.app://oauth/redirect&scope=openid%20offline_access%20https://XXXXX.onmicrosoft.com/api/demo.read';

// just opens and closes the browser with the previous URL
    const browser = await Browser.open({ url: urlLogout});
    Browser.close();

// Then run the logout from plugin
  Plugins.OAuth2Client.logout(environment.oauth2Options)
      .then(() => sessionStorage.clear())
      .catch(reason => { console.error('OAuth logout failed', reason); });

loonix avatar Jun 01 '20 15:06 loonix

hi, any official solution for this?

JCASTANO avatar Jun 19 '20 13:06 JCASTANO

the workaround does not work because login and logout does not use the same browser instance...

tobium avatar Jun 30 '20 10:06 tobium

It does work for me, its not a definitive fix though

loonix avatar Jun 30 '20 10:06 loonix

how do you do the login? via the plugin (with it's native browser usage?)

Are youz forced to type in your username and password after logging out and logging in again?

tobium avatar Jun 30 '20 11:06 tobium

The workaround works for azure b2c, not sure about other types of logins. I have made a repo that is working for logins, I have not impletemented there this workaround, but you can have a picture of how I do it: https://github.com/loonix/capacitor-oauth2-azure-example/blob/master/src/app/home/home.page.ts

Give it a try and tell us how it goes.

loonix avatar Jun 30 '20 11:06 loonix

@tobium you tried in IOS Right? Seems to work on the IOS emulator but not on the device :( . Android works fine on my phone. Workaround only for android then :(.

~Would be great if this plugin could have the logout, as its kind of a deal-breaker for using it

loonix avatar Jul 01 '20 12:07 loonix

~Would be great if this plugin could have the logout, as its kind of a deal-breaker for using it

PRs are welcome ;)

https://github.com/moberwasserlechner/capacitor-oauth2/blob/master/.github/CONTRIBUTING.md#pull-request-guidelines

moberwasserlechner avatar Jul 01 '20 12:07 moberwasserlechner

After some digging I found this, not sure if it will help to develop this feature. If I knew how to implement it I would. https://github.com/Azure-Samples/active-directory-b2c-ios-native-appauth/issues/6

loonix avatar Jul 09 '20 14:07 loonix

@loonix Thanks for the example. Such hints are very helpful as I need less research when starting to work on this task

moberwasserlechner avatar Jul 09 '20 14:07 moberwasserlechner

@tobium I was able to logout with IOS but had to increase the timeout specifically for IOS.

const urlLogout = https://${environment.tenantName}.b2clogin.com/tfp/${environment.tenantName}.onmicrosoft.com/${environment.signInPolicy}/oauth2/v2.0/logout?client_id=${environment.clientID}&response_type=token&redirect_uri=${environment.redirectUrl}&scope=openid%20offline_access%20https://XXXX.onmicrosoft.com/api/demo.read;

 // Workaround to get IOS logout
    if(Capacitor.platform === 'ios'){
      await Browser.open({ url: urlLogout }).finally(() => setTimeout(() => Browser.close(), 4000));
      this.onLogoutClick();
      return;
    }

loonix avatar Jul 16 '20 11:07 loonix

Not able to get it working with any of these solutions, did anyone work out a different way to actually log the user out?

tjelz avatar Jan 28 '21 10:01 tjelz

https://github.com/loonix/capacitor-oauth2-azure-example

Check my repo, and the readme file and see if it helps.

loonix avatar Jan 28 '21 11:01 loonix

+1 for this feature

PieterT2000 avatar Jun 22 '21 09:06 PieterT2000

The workaround works for azure b2c, not sure about other types of logins. I have made a repo that is working for logins, I have not impletemented there this workaround, but you can have a picture of how I do it: https://github.com/loonix/capacitor-oauth2-azure-example/blob/master/src/app/home/home.page.ts

Give it a try and tell us how it goes.

I tried same but logout is not working for me. Any solution for logout in android?

PragyaSingla avatar Jul 20 '21 10:07 PragyaSingla

@PragyaSingla not yet but I try to include this into the upcoming 3.x release, that needs Capacitor 3 as its minimum version.

This is a breaking change so I will not back port it to 2.x.

moberwasserlechner avatar Jul 20 '21 10:07 moberwasserlechner

I'm not able to implement this in 3.0.0 and therefore postpone it.

moberwasserlechner avatar Aug 02 '21 11:08 moberwasserlechner

With this setup I'm able to logout

For iOS await Browser.open({ url }).finally(() => setTimeout(() => { Browser.close(); }, 1500) );

For Android await Browser.open({ url }).finally();

Where url = https://{TENANT_NAME}.b2clogin.com/tfp/{TENANT_NAME}.onmicrosoft.com/{USER_FLOW_NAME}/oauth2/v2.0/logout

SantoshPisini avatar Apr 17 '22 10:04 SantoshPisini

i can confirm that the workaround from @loonix works. For IOS it always works, but for Android it only works if the system browser is Chrome. If the system browser on Android devices is not Chrome, the logout will not work. To fix this issue i'm using the Cordova In App Browser for android, where the system browser can be forced. Here is a working snippet for it with angular:


  import { InAppBrowser } from '@awesome-cordova-plugins/in-app-browser/ngx';
  import { Browser } from '@capacitor/browser';
  import { OAuth2Client } from '@byteowls/capacitor-oauth2';
  import { isPlatform } from '@ionic/angular';

  constructor(private iab: InAppBrowser) {}

  public signOut() {
    const url = 'YOUR_LOGOUT_URL';

    return of(isPlatform('android')).pipe(
      switchMap((isAndroid) => (isAndroid ? this.handleAndroidSignOut(url) : this.handleIosSignOut(url))),
      switchMap(() => from(OAuth2Client.logout(OAUTH_OPTIONS)))
    );
  }

  private handleIosSignOut(url: string) {
    return from(Browser.open({ url })).pipe(
      switchMap(() => from(Browser.addListener('browserPageLoaded', () => {}))), // await page load to make sure logout was called
      switchMap(() => Browser.close())
    );
  }

  private handleAndroidSignOut(url: string) {
    const ref = this.iab.create(url, '_system', 'hidden=yes'); 
    return ref.on('loadstop').pipe(tap(() => ref.close())); // // await page load to make sure logout was called
  }

As a sideeffekt you'll see the Browser popup and close quickly. It would be nice, if this could happen in background for better UX. This should be fixed in the plugin itself.

DwieDima avatar Sep 30 '22 07:09 DwieDima

@DwieDima That looks exactly what would work for me. I have the app-browser working but I'm not sure where is the .pipe coming from? I also can't close the window:

let ref = await InAppBrowser.create(
    `https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/logout`,
    "_system",
    "hidden=yes"
  );
ref.close()

The hidden flag isn't making the window hidden, and the .close() isn't closing it. Other than that it does work as a solution....

I'm trying to get this to work on reactJS PWA ionic + capacitor.

DenysAshikhin avatar Dec 08 '22 21:12 DenysAshikhin

@DenysAshikhin try this promise-based snipped:

  public async signOut(): Promise<void> {
    const url = 'your-auth-url';

    if(isPlatform('android')) {
      await this.handleAndroidSignOut(url);
    } else {
      await this.handleIosSignOut(url);
    }

    await OAuth2Client.logout(OAUTH_OPTIONS);
  }

  private async handleIosSignOut(url: string): Promise<void> {
    await Browser.open({ url });
    await Browser.addListener('browserPageLoaded', () => {});
    await Browser.close();
  }

  private async handleAndroidSignOut(url: string): Promise<void> {
    const ref = this.iab.create(url, '_system');
    ref.show();
    await new Promise(resolve => setTimeout(() => resolve, 300));
    ref.close();
  }

DwieDima avatar Dec 12 '22 13:12 DwieDima

@DwieDima Did you only install "@awesome-cordova-plugins/in-app-browser": "^6.3.0",, or "cordova-plugin-inappbrowser": "^5.0.0" too? It seems npx cap sync doesnt see @awesome-cordova-plugins and only adds inAppbrowser when i also install "cordova-plugin-inappbrowser": "^5.0.0" Making let ref = await InAppBrowser.create(url,"_system",'hidden=yes'); doesnt open chrome browser by default, but shows browser select dialog https://user-images.githubusercontent.com/906026/213331694-87da460c-888b-485c-abd7-b63ced064228.png

mozzi avatar Jan 19 '23 01:01 mozzi