首页 > 解决方案 > AppAuth-Android 在处理非分层 URI 回调意图时出现奇怪问题

问题描述

我在我的应用程序中使用 AppAuth-Android 来处理 OAuth 流程。当流程开始时,我调用https://github.com/openid/AppAuth-Android#obtaining-an-authorization-code步骤startActivityForResults中描述的方法。调用该方法后,会弹出浏览器等待用户登录。

在我的清单中,我有

<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 文档中所述。

在对我的应用程序进行渗透测试期间,发现如果在这个特定时刻(当浏览器用于身份验证时),您按照以下步骤操作,应用程序崩溃

  1. 切换应用程序(例如我打开浏览器,而不是关闭我的应用程序)
  2. 在我的例子中单击一个非分层链接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 不是分层的getQueryParameterNames,则该类java.net.URI会引发异常。

我不确定这是否是与库本身相关的问题,或者是否有可以完成的解决方案(可能会更改清单深度链接处理)。事实是我不知道如何解决这个问题。

如果问题看起来过于综合,并且您需要一些额外的信息来重现问题,请随时询问更多详细信息。谢谢 :)

标签: androidandroid-intentdeep-linkingappauth

解决方案


我假设intent-filter您发布的内容设置为RedirectUriReceiverActivity,但您实际上可以拥有自己的内容,Activity而不是成为中间人。如果您查看源代码,它基本上只做

startActivity(AuthorizationManagementActivity.createResponseHandlingIntent(
                    this, getIntent().getData()));
  1. 创建自己的活动,例如AllUriReceiverActivity
  2. 为此设置意图过滤器(您在上面发布的)AllUriReceiverActivity
  3. onCreate()执行调用之前AllUriReceiverActivity检查是否getIntent().getData()包含分层 URI 。startActivity()

  4. 重用库的RedirectUriReceiverActivity,所以当库更新实例化的方式时你不必担心AuthorizationManagementActivity

所以onCreate()它应该是这样的:

Uri uri = getIntent().getData();

if (uri.isHierarchical()) {
   Intent i = new Intent(context, RedirectUriReceiverActivity.class);
   i.setData(uri);
   startActivity(i);
}
finish();

编辑:此外,为了摆脱对 URI 的处理RedirectUriReceiverActivity,您可以完全删除 AppAuth lib 建议的这一部分:

android.defaultConfig.manifestPlaceholders = [
  'appAuthRedirectScheme': '...'
]

推荐阅读