I am using AppAuth-Android in my app to handle the OAuth flow. When the flow starts, I call the startActivityForResults
method as described in the https://github.com/openid/AppAuth-Android#obtaining-an-authorization-code step. After calling this method, the browser pops up waiting for the user login.
In my manifest I have
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="com.app.name"
android:host="oauth2redirect/login-callback" />
</intent-filter>
that is needed for handling the redirect callback when login step is done, as specified in the AppAuth documentation.
During a penetration test on my app, came to light that if in this particular moment (when browser for authentication is visible), you follow the steps below, the app crash
This is the stack trace of the crash.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: io.app.mobile, PID: 29226
java.lang.RuntimeException: Unable to resume activity {com.app.name/net.openid.appauth.AuthorizationManagementActivity}: java.lang.UnsupportedOperationException: This isn't a hierarchical URI.
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3830)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3862)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6854)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)
Caused by: java.lang.UnsupportedOperationException: This isn't a hierarchical URI.
at android.net.Uri.getQueryParameterNames(Uri.java:1590)
at net.openid.appauth.AuthorizationManagementActivity.extractResponseData(AuthorizationManagementActivity.java:318)
at net.openid.appauth.AuthorizationManagementActivity.handleAuthorizationComplete(AuthorizationManagementActivity.java:259)
at net.openid.appauth.AuthorizationManagementActivity.onResume(AuthorizationManagementActivity.java:234)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1413)
at android.app.Activity.performResume(Activity.java:7307)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3822)
The problem seems to be that opening com.name.app:abcd, makes the app believing that there is a result from the intent and net.openid.appauth.AuthorizationManagementActivity
tries to handle it
private Intent extractResponseData(Uri responseUri) {
if (responseUri.getQueryParameterNames().contains(AuthorizationException.PARAM_ERROR)) {
return AuthorizationException.fromOAuthRedirect(responseUri).toIntent();
}
(...)
}
but the getQueryParameterNames
of the class java.net.URI
throws an exception if the URL is NOT hierarchical.
I am not sure if it is a problem related to the library itself, or if there is a solution that can be accomplished (maybe changing the manifest deep linking handling). The fact is that I do not know how to fix this.
If the question seems too synthetic and you need some additional information to reproduce the problem, feel free to ask for more details. Thanks :)
I assume the intent-filter
you posted is set for RedirectUriReceiverActivity
, but you can actually have your own Activity
instead to be the man-in-the-middle. If you look into the source code it basically does nothing more than
startActivity(AuthorizationManagementActivity.createResponseHandlingIntent(
this, getIntent().getData()));
AllUriReceiverActivity
AllUriReceiverActivity
in onCreate()
of AllUriReceiverActivity
add check if getIntent().getData()
contains
hierarchical URI before performing startActivity()
call.
Reuse library's RedirectUriReceiverActivity
, so you don't need to worry when library updates the way of instantiating AuthorizationManagementActivity
So in onCreate()
it should be sth like this:
Uri uri = getIntent().getData();
if (uri.isHierarchical()) {
Intent i = new Intent(context, RedirectUriReceiverActivity.class);
i.setData(uri);
startActivity(i);
}
finish();
EDIT: Additionally to get rid of the handling your URI by RedirectUriReceiverActivity
, you can remove completely this part suggested by AppAuth lib:
android.defaultConfig.manifestPlaceholders = [
'appAuthRedirectScheme': '...'
]