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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:50:37