【问题标题】:Android Microsoft Authentication Library (MSAL) : Facing issue in token expiry handling, how to refresh token using MSAL Android SDKAndroid Microsoft Authentication Library (MSAL):面临令牌过期处理的问题,如何使用 MSAL Android SDK 刷新令牌
【发布时间】:2020-12-02 12:22:36
【问题描述】:

我正在尝试在 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")
            }
        }
    }
}

或

交互式:

if (activeAccount == null) {
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)
    }
})
}

编辑 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

【问题讨论】:

    标签: android azure microsoft-graph-api access-token msal


    【解决方案1】:

    诊断

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

    应该是什么样子的

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

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

    【讨论】:

    • 我添加了异常日志,今天我在另一个新的 android studio 项目中重新创建了相同的日志。现在,当我尝试静默访问 Graph API 时,仍然出现异常
    • 谢谢,我得到了问题,它与 AUTHORITY URL 有关:private val AUTHORITY = "login.microsoftonline.com/common",它应该是 "login.microsoftonline.com/[tenant_id]"
    • 很高兴听到您解决了问题。使用的消息值得了解 - 如果您遇到更多问题,我的 Azure Post 1 和 Azure Post 2 可能会给您一些想法。
    猜你喜欢
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2022-01-08
    • 2016-01-14
    • 1970-01-01
    相关资源
    最近更新 更多