使用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
相关产品推荐
相关产品推荐

