Android中如何在OkHttp3拦截器中使用Amplify Auth AccessToken?
问题:OkHttp拦截器自动添加Amplify AccessToken导致401错误
在Android项目中使用Amplify SDK Auth获取用户AccessToken时,直接在接口调用里传参的方式能正常运行,但改用OkHttp3拦截器自动为API请求添加AccessToken后,所有请求均返回401错误。以下是两种实现代码,需排查问题原因。
可用实现(正常运行)
override suspend fun getUserProfile(): UserProfile { val session = Amplify.Auth.fetchAuthSession() val token = (session as AWSCognitoAuthSession).userPoolTokens.value?.accessToken ?: throw UnauthorisedAccessException() val currentUser = Amplify.Auth.getCurrentUser() ?: throw UnauthorisedAccessException() return apiService.getUserProfile( accessToken = token, userId = currentUser.userId ).mapToDomain() }
拦截器实现(返回401错误)
class AmplifyAuthorizationHeaderInterceptor : Interceptor { private val coroutineScope = CoroutineScope(Dispatchers.IO) @OptIn(ExperimentalCoroutinesApi::class) override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() // Get the access token from the authenticator. val token = coroutineScope.async { val session = Amplify.Auth.fetchAuthSession() (session as AWSCognitoAuthSession).userPoolTokens.value?.accessToken } token.invokeOnCompletion { request = if (it == null) { request.newBuilder() .header("Authorization", token.getCompleted()!!) .build() }else{ request } } return chain.proceed(request) } }
问题原因与修复方案
核心问题:异步操作导致请求提前发送
OkHttp的intercept方法是同步执行的,但你在拦截器里用coroutineScope.async启动了异步任务获取token,再通过invokeOnCompletion回调修改请求。但回调执行时,chain.proceed(request)已经完成,实际发送的是未添加token的原始请求,因此后端返回401。
修复方案:同步获取token
方案1:用runBlocking等待异步任务完成
直接在拦截器中阻塞线程等待token获取完成,确保修改后的请求才被发送:
class AmplifyAuthorizationHeaderInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() val token = runBlocking(Dispatchers.IO) { val session = Amplify.Auth.fetchAuthSession() (session as AWSCognitoAuthSession).userPoolTokens.value?.accessToken } val modifiedRequest = token?.let { originalRequest.newBuilder() .header("Authorization", it) .build() } ?: originalRequest return chain.proceed(modifiedRequest) } }
方案2:使用Amplify同步API(如果支持)
部分版本的Amplify Auth提供同步版fetchAuthSession,可直接调用无需协程:
class AmplifyAuthorizationHeaderInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() val session = Amplify.Auth.fetchAuthSession() val token = (session as AWSCognitoAuthSession).userPoolTokens.value?.accessToken val modifiedRequest = token?.let { originalRequest.newBuilder() .header("Authorization", it) .build() } ?: originalRequest return chain.proceed(modifiedRequest) } }
额外检查项
- 令牌格式:部分后端要求令牌前缀(如
Bearer),对比可用实现中是否添加了该前缀,拦截器里如果遗漏会导致验证失败。 - 空token处理:若获取token失败,应直接返回原请求或抛出异常,避免发送无效请求。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

