AWS Cognito - 当 ID 令牌需要刷新时 getSessionInBackground 失败

AWS Cognito - getSessionInBackground fails when ID token needs refreshing

我的 ID 令牌有效期为一个小时。一个小时后,当我在服务调用中的 CognitoUser 对象上调用 getSessionInBackground 时,我的调用失败了。如果前一个 ID 令牌已过期,这不是应该 return 一个新的 ID 令牌吗?这种行为不是始终可重现的,这无济于事——它只发生在某些屏幕上。此外,它似乎只发生在 Android,而不是 iOS。

发生这种情况是因为 sdk 中的线程不完全安全,这个错误发生在 aws-sdk-version <2.3 中,因为一个线程读取了正确的值,如果令牌过期,它会清除 cachedToken,什么都不留下供第二个线程读取,第二个线程假定不存在令牌(而第一个线程正在刷新令牌),因此抛出用户未授权异常。

如果您使用的是 aws-sdk2.2,这是一个突出的错误,您可以使用以下代码片段来修复它:

new Thread(new Runnable() {

        @Override
        public void run() {

            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            CognitoUser user = userPool.getCurrentUser();

            user.getSessionInBackground(new AuthenticationHandler() {
                @Override
                public void onSuccess(final CognitoUserSession userSession) {
                    Log.d("Authenticator.java", userSession.getIdToken().getJWTToken().toString());
                    semaphore.release();
                    callback.onSuccess(userSession);
                }

                @Override
                public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String UserId) {

                    semaphore.release();
                    callback.onNeedsPassword();
                }

                @Override
                public void getMFACode(MultiFactorAuthenticationContinuation continuation) {

                    semaphore.release();
                    callback.onNeedsPassword();
                }

                @Override
                public void onFailure(final Exception exception) {

                    semaphore.release();
                    callback.onFailure(exception);
                }
            });
        }
    }).start();

当前的 aws-sdk-2.4 版本中还有一个与此相关的错误,如果您多次调用 aws 以获取新的 ID 令牌,它会增加您的网络流量。(这是一个边缘案例,但仍然) https://github.com/aws/aws-sdk-android/pull/272