Библиотека аутентификации Microsoft Android (MSAL): проблема с обработкой истечения срока действия токена, как обновить токен с помощью MSAL Android SDK

#android #azure #microsoft-graph-api #access-token #msal

#Android #azure #microsoft-graph-api #токен доступа #azure-ad-msal

Вопрос:

Я пытаюсь реализовать MSAL в Android для входа пользователя в систему с использованием его учетных данных 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

Ответ №1:

ДИАГНОСТИКА

Можете ли вы предоставить какие-либо сведения об ошибке? И вы отследили сообщение об обновлении токена HTTPS?

КАК ЭТО ДОЛЖНО ВЫГЛЯДЕТЬ

Библиотека MSAL должна отправлять сообщение о предоставлении обновления токена, как в шагах 15 и 16 моего сообщения в блоге.

Мое приложение использует библиотеки AppAuth, но MSAL будет работать таким же образом, поскольку это стандартно для мобильного приложения.

Комментарии:

1. Я добавил журналы исключений, сегодня я воссоздал то же самое в другом новом проекте Android Studio. Теперь, когда я пытаюсь получить доступ к API Graph в автоматическом режиме, я по-прежнему получаю исключение

2. Спасибо, я получил проблему, это было с URL-адресом ПОЛНОМОЧИЙ: private val AUTHORITY = » login.microsoftonline.com/common «, это должно было быть » login.microsoftonline.com /[tenant_id] »

3. Приятно слышать, что вы решили свои проблемы. Стоит разобраться в используемых сообщениях — если вы столкнетесь с дальнейшими проблемами, мои сообщения Azure 1 и сообщения Azure 2 могут дать вам несколько идей.