Android Microsoft身份验证库MSAL:在令牌到期处理中面临的问题,如何使用MSAL Android SDK刷新令牌

问题描述

我正在尝试在Android中实现MSAL,以便使用其Microsoft凭据登录用户。 全新安装后,第一次可以获取令牌,并将其进一步用于访问Microsoft Graph API。

由于默认情况下,MSAL令牌的到期时间为1小时,如果尝试重新启动该应用,则在1小时后,我将面临令牌身份验证异常。

现在我被困在如何再次刷新令牌上?

在MSAL中,我遵循了示例,但是没有任何地方提到使用Android SDK刷新令牌[我们可以使用API​​调用来获取和刷新令牌,但是我没有使用API​​方法,而是在将SDK用于处理所有流程。]

我现在正试图解决这个问题。

private val AUTHORITY = "https://login.microsoftonline.com/common"
private var mSingleAccountApp: ISingleAccountPublicClientApplication? = null
private var mActiveAccount: MultiTenantAccount? = null

fun startTokenProcess(
    activity: LoginActivity,preferenceManager: PreferenceManager
) {
    this.mActivity = activity
    this.mPreferences = preferenceManager

    mSingleAccountApp = null

    // Creates a PublicClientApplication object with res/raw/auth_config.json
    PublicClientApplication.createSingleAccountPublicClientApplication(activity,R.raw.auth_config,object : IPublicClientApplication.ISingleAccountApplicationCreatedListener {
            override fun onCreated(application: ISingleAccountPublicClientApplication?) {

                // initialization of ISingleAccountPublicClientApplication object
                mSingleAccountApp = application

                // check for existence of any account linked in cache
                mSingleAccountApp?.getCurrentAccountAsync(object :
                    ISingleAccountPublicClientApplication.CurrentAccountCallback {
                    override fun onAccountLoaded(activeAccount: IAccount?) {

                        if (activeAccount == null) {

                            // nothing found
                            // start new interactive signin
                            mSingleAccountApp?.signIn(mActivity,"",getScopes(),object : AuthenticationCallback {
                                    override fun onSuccess(authenticationResult: IAuthenticationResult?) {
                                        mActiveAccount =
                                            authenticationResult?.account as MultiTenantAccount?

                                        // save access token in SP
                                        authenticationResult?.accessToken?.let {
                                            mPreferences.putString(
                                                KEY_ACCESS_TOKEN,it
                                            )
                                        }

                                        callGraphAPI(authenticationResult?.accessToken)
                                    }

                                    override fun onCancel() {
                                        Timber.d("Canceled")
                                    }

                                    override fun onError(exception: MsalException?) {
                                        Timber.d(exception?.errorCode)
                                    }
                                })
                        } else {
                            // Founded an valid account in cache
                            // get account token from SP,call Graph API
                            // todo: check if access token expired ? ask for new token,clear SP
                            mActiveAccount = activeAccount as MultiTenantAccount?
                            val accessToken = mPreferences.getString(KEY_ACCESS_TOKEN)
                            if (accessToken != null) {
                               
                                callGraphAPI(accessToken)
                            }
                        }
                    }

                    override fun onAccountChanged(
                        priorAccount: IAccount?,currentAccount: IAccount?
                    ) {
                        Timber.d("Founded an account $priorAccount")
                        Timber.d("Founded an account $currentAccount")
                    }

                    override fun onError(exception: MsalException) {
                        Timber.e(exception)
                    }
                })
            }

            override fun onError(exception: MsalException?) {
                Timber.e(exception)
            }
        })
}

我尝试再次以静默方式和交互式方式获取令牌,但没有成功。

静默:

mSingleAccountApp?.acquireTokenSilentAsync(getScopes(),AUTHORITY,getAuthSilentCallback())

private fun getAuthSilentCallback(): SilentAuthenticationCallback {
    return object : SilentAuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            Timber.d("Successfully authenticated")

            /* Successfully got a token,use it to call a protected resource - MSGraph */
            callGraphAPI(authenticationResult?.accessToken)
        }

        override fun onError(exception: MsalException) {
            /* Failed to acquireToken */
            Timber.e("Authentication failed: $exception")
            if (exception is MsalClientException) {
                Timber.e("Exception inside MSAL,more info inside MsalError.java ")
            } else if (exception is MsalServiceException) {
                Timber.e("Exception when communicating with the STS,likely config issue")
            } else if (exception is MsalUiRequiredException) {
                Timber.e("Tokens expired or no session,retry with interactive")
            }
        }
    }
}

OR

互动地:

if (activeAccount == null) {
mSingleAccountApp?.signIn(mActivity,object : AuthenticationCallback {
    override fun onSuccess(authenticationResult: IAuthenticationResult?) {
        mActiveAccount =
            authenticationResult?.account as MultiTenantAccount?

        // save access token in SP
        authenticationResult?.accessToken?.let {
            mPreferences.putString(
                KEY_ACCESS_TOKEN,it
            )
        }

        callGraphAPI(authenticationResult?.accessToken)
    }

    override fun onCancel() {
        Timber.d("Canceled")
    }

    override fun onError(exception: MsalException?) {
        Timber.d(exception?.errorCode)
    }
})
}

编辑1:

我得到的例外情况:

CoreHttpProvider[sendRequestInternal] - 414Graph service exception Error code: InvalidAuthenticationToken

CoreHttpProvider[sendRequestInternal] - 414Error message: Access token has expired.

CoreHttpProvider[sendRequestInternal] - 414SdkVersion : graph-java/v1.9.0

CoreHttpProvider[sendRequestInternal] - 414Authorization : Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI[...]

CoreHttpProvider[sendRequestInternal] - 414Graph service exception Error code: InvalidAuthenticationToken

Throwable detail: com.microsoft.graph.http.GraphServiceException: Error code: InvalidAuthenticationToken
    Error message: Access token has expired.

当我再次尝试以静默方式获取令牌时,出现以下异常:

l$getAuthSilentCallback: Authentication failed: com.microsoft.identity.client.exception.MsalServiceException: AADSTS700016: Application with identifier 'Some_ID' was not found in the directory 'Some_ID'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
    Trace ID: 'Some_ID'
    Correlation ID: 'Some_ID'
    Timestamp: 2020-08-15 06:06:11Z

getAuthSilentCallback: Exception when communicating with the STS,likely config issue

编辑2 根据我遇到的关于配置问题的例外情况,我遇到了问题,它与我使用的授权URL有关。 msal-client-application-configuration

解决方法

诊断

您可以提供任何错误详细信息吗?并且您是否跟踪了HTTPS令牌刷新消息?

应该看什么

MSAL库应该发送刷新令牌授予消息,如steps 15 and 16 of my blog post中一样。

我的应用程序使用AppAuth库,但是MSAL将以相同的方式工作,因为这对于移动应用程序是标准的。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...