You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AppAuth的OAuth2隐式授权模式获取AccessToken问题咨询

嘿,我来帮你搞定AppAuth隐式授权模式下,从浏览器返回应用后的AccessToken处理逻辑,这可是踩过不少坑总结出来的经验~

一、ReceiverActivity核心处理代码

当从浏览器跳转回你的ReceiverActivity时,需要在页面创建或新Intent触发时,解析AppAuth返回的授权响应。这里分两种场景处理(适配不同启动模式):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 首次创建时处理返回的授权响应
    handleAuthResponse(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
    // 当Activity为singleTop/singleTask模式时,新Intent会走这个方法
    handleAuthResponse(intent);
}

private void handleAuthResponse(Intent intent) {
    // 解析AppAuth返回的响应和异常信息
    AuthorizationResponse authResponse = AuthorizationResponse.fromIntent(intent);
    AuthorizationException authException = AuthorizationException.fromIntent(intent);

    if (authResponse != null) {
        // 隐式授权模式下,AccessToken直接包含在响应里
        String accessToken = authResponse.accessToken;
        long expiresIn = authResponse.expiresIn;
        String idToken = authResponse.idToken; // 如果请求了openid scope才会有

        // 把token存到本地(比如SharedPreferences),方便后续接口调用
        saveTokensToLocal(accessToken, expiresIn, idToken);

        // 跳转到主业务页面,结束当前ReceiverActivity
        startActivity(new Intent(this, MainActivity.class));
        finish();
    } else if (authException != null) {
        // 处理授权失败的情况:用户取消、服务器错误、参数不合法等
        Log.e("ReceiverActivity", "授权失败: " + authException.getMessage());
        Toast.makeText(this, "授权失败:" + authException.getMessage(), Toast.LENGTH_SHORT).show();
        finish();
    }
}

private void saveTokensToLocal(String accessToken, long expiresIn, String idToken) {
    SharedPreferences prefs = getSharedPreferences("AuthStorage", MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString("access_token", accessToken);
    // 计算token过期时间点,方便后续判断是否需要刷新
    editor.putLong("expires_at", System.currentTimeMillis() + (expiresIn * 1000));
    if (idToken != null) {
        editor.putString("id_token", idToken);
    }
    editor.apply();
}
二、常见坑点排查
  • 必须配置正确的Intent Filter:在AndroidManifest.xml中,ReceiverActivity的scheme必须和授权请求的redirectUri完全匹配,否则浏览器无法跳转回你的应用:
<activity android:name=".ReceiverActivity"
    android:launchMode="singleTask"> <!-- 建议设置为singleTask避免多实例 -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- 这里的scheme和host要和你授权请求中的redirectUri一致,比如myapp://oauth2callback -->
        <data
            android:scheme="myapp"
            android:host="oauth2callback" />
    </intent-filter>
</activity>
  • 授权请求的参数要符合隐式规范:发起请求时,ResponseType必须指定为TOKEN,redirectUri要和Manifest配置一致:
// 构建授权请求示例
AuthorizationServiceConfiguration serviceConfig = new AuthorizationServiceConfiguration(
        Uri.parse("https://你的授权服务器地址/auth"), // 授权端点
        Uri.parse("https://你的授权服务器地址/token") // token端点(隐式模式其实用不上,但AppAuth要求传)
);

Uri redirectUri = Uri.parse("myapp://oauth2callback");
AuthorizationRequest authRequest = new AuthorizationRequest.Builder(
        serviceConfig,
        "你的客户端ID",
        ResponseTypeValues.TOKEN, // 隐式模式必须用TOKEN
        redirectUri
)
        .setScopes("openid", "profile") // 根据业务需求添加scope
        .build();
  • PendingIntent的requestCode建议唯一:你之前用request.hashCode()作为requestCode是没问题的,避免多个授权请求的PendingIntent冲突。

内容的提问来源于stack exchange,提问作者ccaring

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:50:42