当前位置: 首页 > 知识库问答 >
问题:

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

邓威
2023-03-14

我正在尝试在Android中实现MSAL,以便使用他们的微软凭据登录用户。在全新安装时,我第一次能够获取令牌,并进一步使用它来访问微软图形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

共有1个答案

南宫胡媚
2023-03-14

诊断

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

它应该是什么样子

MSAL库应该发送刷新令牌授予消息,如我博客文章的步骤15和16所示。

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

 类似资料:
  • 我试图弄清楚我应该如何坚持身份验证。 假设用户使用电子邮件和密码成功进行身份验证。然后服务器生成并返回两个令牌: accesstoken(jwt过期15分钟)将存储在浏览器存储中 refreshtoken(jwt过期7天)作为安全cookie 当将访问令牌存储在本地存储(或会话存储)中时,React 应用程序将简单地检查它是否存在于存储中并继续渲染私有路由。因此,这意味着如果用户有一个无效/被盗的

  • 我正在做一个项目(没有生产级别,只是为了提高我的技能),我正在使用JWT来处理身份验证。从我所读到的内容来看,仅使用JWT作为访问令牌是非常不安全的,因此我们需要刷新令牌。因此,在登录时,服务器返回一个访问令牌和一个刷新令牌(我将存储在httpOnly cookie中)。访问令牌在短时间内到期,但刷新令牌在到期时用于获取新令牌。 我的问题是,我们何时使用刷新令牌来获取新的访问令牌?是当用户想要获得

  • 我引用的是另一篇讨论在JWT中使用刷新令牌的SO帖子。 JWT(JSON Web令牌)自动延长到期时间 我有一个应用程序,它具有一个非常通用的体系结构,在这个体系结构中,我的客户机(web和移动)与一个REST API对话,然后再与一个服务层和数据层对话。 令牌每小时由客户端刷新一次。 如果用户令牌未被刷新(用户处于非活动状态且应用程序未打开)并且过期,则无论何时他们想要恢复,都需要登录。 我看到

  • 我有一个Xamarin.forms iOS/Android应用程序,必须根据Microsoft Azure B2C广告对用户进行身份验证。 我已经添加了Microsoft.Identity.Client NuGet,并使用它进行身份验证。 登录工作正常,我可以使用返回的令牌调用我们自己的Azure托管服务。 但是,如果我提供了这个作用域,库会抛出不支持的异常。 我的问题是:这是因为MSAL目前根本

  • 我有一个LaravelAPI(实际上是LumenAPI)服务于VueJS前端。Vue应用程序允许用户登录到谷歌。然后将Google令牌发送回Lumen API,后者使用Google验证令牌,然后验证电子邮件地址是否为有效用户。然后它生成一个令牌,与用户一起存储在数据库中,并返回用户对象。 我没有使用Passport或jwt auth之类的东西。那么现在,我如何使用默认的Auth中间件来验证(现在已