AppAuth-Android 处理非分层 URI 回调意图的奇怪问题
AppAuth-Android strange problem in handling NOT hierarchical URI callback intent
我在我的应用程序中使用 AppAuth-Android 来处理 OAuth 流程。当流程开始时,我调用 startActivityForResults
方法,如 https://github.com/openid/AppAuth-Android#obtaining-an-authorization-code 步骤中所述。调用该方法后,弹出浏览器等待用户登录。
在我的清单中我有
<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>
完成登录步骤后处理重定向回调所需的,如 AppAuth 文档中所述。
在对我的应用程序进行渗透测试时,发现如果在这个特定时刻(当浏览器可以看到身份验证时),您按照以下步骤操作,应用程序就会崩溃
- 切换应用程序(例如,我打开浏览器,而不是关闭我的应用程序)
- 点击一个不分层的 link,com.name.app:abcd 在我的例子中(这个 URL 是测试人员现成的)
这是崩溃的堆栈跟踪。
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)
问题似乎是打开 com.name.app:abcd,使应用程序相信有一个来自意图的结果,并且 net.openid.appauth.AuthorizationManagementActivity
试图处理它
private Intent extractResponseData(Uri responseUri) {
if (responseUri.getQueryParameterNames().contains(AuthorizationException.PARAM_ERROR)) {
return AuthorizationException.fromOAuthRedirect(responseUri).toIntent();
}
(...)
}
但是如果 URL 不是分层的,class java.net.URI
的 getQueryParameterNames
会抛出异常。
我不确定这是否是与库本身相关的问题,或者是否有可以完成的解决方案(可能更改清单深度 linking 处理)。事实上,我不知道如何解决这个问题。
如果问题看起来过于综合,您需要一些额外的信息来重现问题,请随时询问更多详细信息。谢谢:)
我假设您发布的 intent-filter
设置为 RedirectUriReceiverActivity
,但实际上您可以拥有自己的 Activity
而不是中间人。如果你查看 source code 它基本上只做
startActivity(AuthorizationManagementActivity.createResponseHandlingIntent(
this, getIntent().getData()));
- 创建您自己的 Activity 例如
AllUriReceiverActivity
- 为此
AllUriReceiverActivity
设置 intent-filter(您在上面发布的)
在 AllUriReceiverActivity
的 onCreate()
中添加检查 getIntent().getData()
是否包含
执行 startActivity()
调用之前的分层 URI。
复用library的RedirectUriReceiverActivity
,不用担心library更新实例化的方式AuthorizationManagementActivity
所以在onCreate()
中应该是这样的:
Uri uri = getIntent().getData();
if (uri.isHierarchical()) {
Intent i = new Intent(context, RedirectUriReceiverActivity.class);
i.setData(uri);
startActivity(i);
}
finish();
编辑:此外,要摆脱 RedirectUriReceiverActivity
对 URI 的处理,您可以完全删除 AppAuth lib 建议的这部分:
android.defaultConfig.manifestPlaceholders = [
'appAuthRedirectScheme': '...'
]
我在我的应用程序中使用 AppAuth-Android 来处理 OAuth 流程。当流程开始时,我调用 startActivityForResults
方法,如 https://github.com/openid/AppAuth-Android#obtaining-an-authorization-code 步骤中所述。调用该方法后,弹出浏览器等待用户登录。
在我的清单中我有
<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>
完成登录步骤后处理重定向回调所需的,如 AppAuth 文档中所述。
在对我的应用程序进行渗透测试时,发现如果在这个特定时刻(当浏览器可以看到身份验证时),您按照以下步骤操作,应用程序就会崩溃
- 切换应用程序(例如,我打开浏览器,而不是关闭我的应用程序)
- 点击一个不分层的 link,com.name.app:abcd 在我的例子中(这个 URL 是测试人员现成的)
这是崩溃的堆栈跟踪。
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)
问题似乎是打开 com.name.app:abcd,使应用程序相信有一个来自意图的结果,并且 net.openid.appauth.AuthorizationManagementActivity
试图处理它
private Intent extractResponseData(Uri responseUri) {
if (responseUri.getQueryParameterNames().contains(AuthorizationException.PARAM_ERROR)) {
return AuthorizationException.fromOAuthRedirect(responseUri).toIntent();
}
(...)
}
但是如果 URL 不是分层的,class java.net.URI
的 getQueryParameterNames
会抛出异常。
我不确定这是否是与库本身相关的问题,或者是否有可以完成的解决方案(可能更改清单深度 linking 处理)。事实上,我不知道如何解决这个问题。
如果问题看起来过于综合,您需要一些额外的信息来重现问题,请随时询问更多详细信息。谢谢:)
我假设您发布的 intent-filter
设置为 RedirectUriReceiverActivity
,但实际上您可以拥有自己的 Activity
而不是中间人。如果你查看 source code 它基本上只做
startActivity(AuthorizationManagementActivity.createResponseHandlingIntent(
this, getIntent().getData()));
- 创建您自己的 Activity 例如
AllUriReceiverActivity
- 为此
AllUriReceiverActivity
设置 intent-filter(您在上面发布的)
在
AllUriReceiverActivity
的onCreate()
中添加检查getIntent().getData()
是否包含 执行startActivity()
调用之前的分层 URI。复用library的
RedirectUriReceiverActivity
,不用担心library更新实例化的方式AuthorizationManagementActivity
所以在onCreate()
中应该是这样的:
Uri uri = getIntent().getData();
if (uri.isHierarchical()) {
Intent i = new Intent(context, RedirectUriReceiverActivity.class);
i.setData(uri);
startActivity(i);
}
finish();
编辑:此外,要摆脱 RedirectUriReceiverActivity
对 URI 的处理,您可以完全删除 AppAuth lib 建议的这部分:
android.defaultConfig.manifestPlaceholders = [
'appAuthRedirectScheme': '...'
]