capacitor-community / generic-oauth2

Generic Capacitor OAuth 2 client plugin. Stop the war in Ukraine!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: USER_CANCELLED response on Android and IOS

UnclearMaker opened this issue · comments

Capacitor version:

Run npx cap doctor:

npx cap doctor

   Capacitor Doctor

Latest Dependencies:

  @capacitor/cli: 3.2.4
  @capacitor/core: 3.2.4
  @capacitor/android: 3.2.4
  @capacitor/ios: 3.2.4

Installed Dependencies:

  @capacitor/android: 3.2.0
  @capacitor/core: 3.2.0
  @capacitor/cli: 3.2.0
  @capacitor/ios: 3.2.0

[success] Android looking great! �
[error] Xcode is not installed
npm notice
npm notice New major version of npm available! 7.22.0 -> 8.0.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.0.0
npm notice Run npm install -g npm@8.0.0 to update!
npm notice

Library version:

  • 3.0.1

OAuth Provider:

  • Azure AD

Your Plugin Configuration

{
	appId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
	authorizationBaseUrl: 'https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/v2.0/authorize',
	accessTokenEndpoint: 'https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/v2.0/token',
	responseType: 'code',
	pkceEnabled: true,
	logsEnabled: true,
	scope: 'https://xxxx.onmicrosoft.com/xxxxxx/tasks.read https://xxxx.onmicrosoft.com/xxxxxx/tasks.write',
	web: {
		redirectUrl: 'http://localhost:8100/',
		windowOptions: 'width=642,height=586,location=off,scrollbars=on'
	},
	android: {
		redirectUrl: 'msauth://id.package.my/xxxxxxxxxxxxxxxxxxxxxxxxxxxx' // URL encoded signature hash
	},
	ios: {
		pkceEnabled: true, // workaround for bug #111
    	redirectUrl: 'msauth.id.package.my://auth'
	}
}

Affected Platform(s):

  • Android
  • Android version: 8.0.0. Device model: SM-G935F

Current Behavior

This is an Ionic 5 app.

On Windows/Web (Chrome browser), we are able to log in as expected.

On Android we get plugin response USER_CANCELLED.

What is different on Android compared to Web is that on the login.microsoftonline.com browser login page we are shown a second screen (after logging in) saying:

Are you trying to sign in to XXXXX?

Where XXXXX is the name of our SPA/Android app registration in Azure. Beneath are two buttons: Cancel and Continue. Selecting Continue (or Cancel) does the same thing, returns to the app and displays an error to the app/webview console:
Error: USER_CANCELLED at Object.cap.fromNative (http://localhost/:432.32) at <anonymous>:1:18.

The plugin doesn't seem to log any information like I usually see on the web version (i.e. info prefixed with I/Capacitor/OAuth2ClientPlugin:)

When I check the Azure AD logs, I see an authentication Failure followed by an immediate Success. The failure details includes:

Sign-in error code	
50199
Failure reason	
For security reasons, user confirmation is required for this request. Please repeat the request allowing user interaction.
Additional Details	
MFA requirement satisfied by claim in the token

My understanding is that the Failure/Success happens whilst on the Azure login pages. The Failure triggers the display of the Are you trying to sign in to XXXXX? message, which then, after selecting Continue causes the Success message. But I may be wrong on this.

The error code details for the above 50199 error can be found here. The details being:

AADSTS50199 | CmsiInterrupt - For security reasons, user confirmation is required for this request. Because this is an "interaction_required" error, the client should do interactive auth. This occurs because a system webview has been used to request a token for a native application - the user must be prompted to ask if this was actually the app they meant to sign into. To avoid this prompt, the redirect URI should be part of the following safe list:http://https://msauth://(iOS only)msauthv2://(iOS only)chrome-extension:// (desktop Chrome browser only)

My understanding is that msauth Android is being called by a webview, and because it doesn't trust the webview, it requests the extra verification from the user that the app they are logging into is the one they intend to log into. (related comment).

In addition to the above configuration, I have tried each permutation of handleResultOnNewIntent and handleResultOnActivityResult. All yield the same result, except for:

handleResultOnNewIntent: true,
handleResultOnActivityResult: true

Which displays to the console:
Error: ERR_GENERAL at Object.cap.fromNative (http://localhost:432:32) at <anonymous>:1:18. Again, there is no other info logged to the console.

I've tried every possible fix as specified in the plugin documentation as well as fixes discussed in the issues repo section. Nothing has worked.

Expected Behavior

After logging in on Android, I expect the tokens to be returned to the app/webview so that the app can call the API using Bearer auth.

I noticed in one of the issues that someone else got this plugin working with Ionic, so I'm hoping Ionic isn't a show stopper and that we can resolve this issue.

Thanks!

By way of an update. I have set up and tested the Apple/IOS version of the Ionic app. I get the same set of screens described above. The only difference is:

After clicking "Continue" on the Azure auth popup, we get an additional popup message saying: "Safari cannot open the page because the address is invalid.". After that, the same thing happens, we are taken back to the app, and the error message we get is: Error: USER_CANCELLED: CapacitorException@capacitor://localhost/vendor.js:94505:14 user-script:2:424:49

So the problem is on Apple/IOS as well as Android.

I would greatly appreciate a response to this issue. Even if it's to say when you hope to be able to look at it.

Many thanks!

Hi there. I can see that this was assigned to Android, but the issue is also happening on IOS (as detailed in my previous comment). Could you please give an indication when you might be able to look at this? Many thanks.

commented

I can confirm I'm getting the same issue on Android. However, iOS appears to be working.
I cannot find a work around for Anddroid. This is a bit of a show stopper!

Same here

I have the same issue with Azure provider. Any insights?

I have the same issue with the 3.0.1 version. Any solution or workaround for this issue as temp solution?

OAuth rejected Error: USER_CANCELLED

Thanks in advance

So it turns out the USER_CANCELLED response was caused by a different configuration issue on each environment, which coincidentally caused the same response to be returned. I had mistakenly thought the issue was in the plugin itself, i.e. that it wasn't able to handle Azure AD's CmsiInterrupt flow, but it turns out that was incorrect.

The Android issue was that a second Activity element ("net.openid.appauth.RedirectUriReceiverActivity") was required in AndroidManifest.xml file. We only had a single Activity element ("com.company.project.MainActivity"), and we were missing the android:host parameter too. The readme documentation has been updated to explain it here: https://github.com/moberwasserlechner/capacitor-oauth2#android-1.

The IOS issue was that the CFBundleURLSchemes string was incorrectly set to com.yourcompany.yourproject rather than msauth.com.yourcompany.yourproject (i.e. it was missing the msauth. prefix). The readme documentation explains it here: https://github.com/moberwasserlechner/capacitor-oauth2#ios.

One other thing to note was that we did not set the resourceUrl as our Azure SPA app registration referenced a second Azure API app registration because it needed to obtain additional/custom scopes. The readme documentation has been updated to explain it here: https://github.com/moberwasserlechner/capacitor-oauth2#custom-scopes.

Thanks to the plugin developer @moberwasserlechner for his support in identifying the configuration issues and for updating the Azure documentation section (https://github.com/moberwasserlechner/capacitor-oauth2#azure-active-directory--azure-ad-b2c) to help users configure their apps correctly in the future.