Open loonix opened 4 years ago
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); });
hi, any official solution for this?
the workaround does not work because login and logout does not use the same browser instance...
It does work for me, its not a definitive fix though
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?
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.
@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
~Would be great if this plugin could have the logout, as its kind of a deal-breaker for using it
PRs are welcome ;)
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 Thanks for the example. Such hints are very helpful as I need less research when starting to work on this task
@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;
}
Not able to get it working with any of these solutions, did anyone work out a different way to actually log the user out?
https://github.com/loonix/capacitor-oauth2-azure-example
Check my repo, and the readme file and see if it helps.
+1 for this feature
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 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
.
I'm not able to implement this in 3.0.0
and therefore postpone it.
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
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 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 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 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
I just call 'authorize' again with my logout url. This works for me.
getAzureB2cOAuth2Options(logout: boolean = false): OAuth2AuthenticateOptions {
return {
...
authorizationBaseUrl: `https://....onmicrosoft.com/.../oauth2/v2.0/` + (!logout ? 'authorize' : 'logout'),
...
};
}
...
logout() {
GenericOAuth2.authenticate(this.getAzureB2cOAuth2Options(true))
.then(async response => {
console.log('OAuth response', response);
})
.catch(reason => {
console.error('OAuth rejected', reason);
});
}
It would be nice if the plugin would handle it automatically if we provided the logoutUrl in the options.
Sorry if this is a stupid question, but I'm getting lost in this. Is anything supposed to work regarding logout?
I'm trying it on the web and Android, but pretty much nothing happens. It doesn't clear the tokens from storage, and it doesn't redirect to the logout url. The promise returns true, there is no error... but nothing happens.
I'm doing it pretty much the same as the example in the docs here:
GenericOAuth2.logout(oauth2LogoutOptions, this.accessToken).then(() => {
// do something
}).catch(reason => {
console.error('OAuth logout failed', reason);
});
If it is not expected to work, then I don't really get:
Again, sorry if it's a stupid question, but all of this is quite confusing and misleading.
Btw. we have our own IdentityServer4, and the login is working just fine. Just not the logout
UPDATE: After trying different workarounds, the approach suggested by @noahkriesi works best for my use case: https://github.com/capacitor-community/generic-oauth2/issues/97#issuecomment-2178188975. Thanks!
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
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