Ich habe eine App, in der sich Benutzer in Office365 mit AzureAD-Bibliothek für Android authentifizieren .

Es funktioniert gut, Benutzer können sich authentifizieren und mit der App arbeiten. Leider treffen sie nach einer Weile AuthenticationException mit ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED als Fehlercode.

Ich habe die Quellcode von AzurelAD. Der einzige Ort, an dem dieses Problem auftritt, ist die Methode acquireTokenAfterValidation():

private AuthenticationResult acquireTokenAfterValidation(CallbackHandler callbackHandle,
        final IWindowComponent activity, final boolean useDialog,
        final AuthenticationRequest request) {
    Logger.v(TAG, "Token request started");

    // BROKER flow intercepts here
    // cache and refresh call happens through the authenticator service
    if (mBrokerProxy.canSwitchToBroker()
            && mBrokerProxy.verifyUser(request.getLoginHint(),
                    request.getUserId())) {
        .......
        Logger.v(TAG, "Token is not returned from backgroud call");
        if (!request.isSilent() && callbackHandle.callback != null && activity != null) {
            ....
        } else {
            // User does not want to launch activity
            String msg = "Prompt is not allowed and failed to get token:";
            Logger.e(TAG, msg, "", ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED);
            callbackHandle.onError(new AuthenticationException(
                    ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED, msg));
        }

        // It will start activity if callback is provided. Return null here.
        return null;
    } else {
        return localFlow(callbackHandle, activity, useDialog, request);
    }
}

Mein Quellcode:

authenticator.getAccessTokenSilentSync(getMailService());

public class Authenticator {
    ..............
    public String getAccessTokenSilentSync(ServiceInfo serviceInfo) {
        throwIfNotInitialized();
        return getAuthenticationResultSilentSync(serviceInfo).getAccessToken();
    }

    private AuthenticationResult getAuthenticationResultSilentSync(ServiceInfo serviceInfo) {
        try {
            return authenticationContext.acquireTokenSilentSync(
                    serviceInfo.ServiceResourceId,
                    Client.ID,
                    userIdentity.getAdUserId());
        } catch (AuthenticationException ex) {
            // HERE THE EXCEPTION IS HANDLED.
        }
    }
    ..............
} 

Stacktrace bekomme ich:

    <package name>.data_access.error_handler.AuthenticationExceptionWithServiceInfo: Refresh token is failed and prompt is not allowed
    at com.microsoft.aad.adal.AuthenticationContext.localFlow(AuthenticationContext.java:1294)
    at com.microsoft.aad.adal.AuthenticationContext.acquireTokenAfterValidation(AuthenticationContext.java:1229)
    at com.microsoft.aad.adal.AuthenticationContext.acquireTokenLocalCall(AuthenticationContext.java:1123)
    at com.microsoft.aad.adal.AuthenticationContext.refreshToken(AuthenticationContext.java:1609)
    at com.microsoft.aad.adal.AuthenticationContext.localFlow(AuthenticationContext.java:1261)
    at com.microsoft.aad.adal.AuthenticationContext.acquireTokenAfterValidation(AuthenticationContext.java:1229)
    at com.microsoft.aad.adal.AuthenticationContext.acquireTokenLocalCall(AuthenticationContext.java:1123)
    at com.microsoft.aad.adal.AuthenticationContext.refreshToken(AuthenticationContext.java:1609)
    at com.microsoft.aad.adal.AuthenticationContext.localFlow(AuthenticationContext.java:1261)
    at com.microsoft.aad.adal.AuthenticationContext.acquireTokenAfterValidation(AuthenticationContext.java:1229)
    at com.microsoft.aad.adal.AuthenticationContext.acquireTokenLocalCall(AuthenticationContext.java:1123)
    at com.microsoft.aad.adal.AuthenticationContext.access$600(AuthenticationContext.java:58)
    at com.microsoft.aad.adal.AuthenticationContext$4.call(AuthenticationContext.java:1072)
    at com.microsoft.aad.adal.AuthenticationContext$4.call(AuthenticationContext.java:1067)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)

Version der AzureAD-Bibliothek, die ich verwende: 1.1.7 (um zu verhindern, dass zu alte Versionen beschuldigt werden - ich habe die Änderungsliste seit 1.1.7 bis 1.1.11 überprüft und nichts im Zusammenhang mit Fragen gefunden)

Problem: Im Moment behandle ich diesen Fehler als Signal, über den Benutzer zum Anmeldebildschirm zu gelangen. Meiner Meinung nach führt dies zu einer schlechten Erfahrung für den Benutzer. Die Tatsache, dass es sehr häufig vorkommt und viele Benutzer betrifft, macht es noch schlimmer.

Frage: Kann ich etwas anderes tun, um dieses AuthenticationException zu vermeiden oder es irgendwie zu umgehen (d. h. vermeiden, dass der Benutzer erneut Anmeldeinformationen eingibt).

3
Konstantin Loginov 5 Jän. 2016 im 17:37

2 Antworten

Beste Antwort

Haben Sie überprüft, dass AuthenticationContext.acquireTokenSilentSync() wirklich die Methode ist, die Sie aufrufen möchten?

Die Dokumente geben an, dass diese Methode explizit keine Eingabeaufforderung anzeigt. Aus den Dokumenten:

This is sync function. It will first look at the cache and automatically checks for the token expiration. Additionally, if no suitable access token is found in the cache, but refresh token is available, the function will use the refresh token automatically. This method will not show UI for the user. If prompt is needed, the method will return an exception.

Das von Ihnen ausgestellte Aktualisierungstoken sollte für dieses AAD-Buch zwei Wochen dauern. Nach Ablauf des Aktualisierungstokens wird von den Benutzern erwartet, dass sie sich erneut authentifizieren. Können Sie den Nettoverkehr mit Fiddler oder Charles und den Ablauf der Token überprüfen? Wenn Sie überprüfen können, ob die Token vor ihrem Ablauf nicht aktualisiert werden können, weist dies möglicherweise auf einen Fehler in der AD-Bibliothek hin.

Um den Unterschied zwischen den Methoden in AuthenticationContext zu verdeutlichen, gibt es zwei Kategorien von Methoden: "stille" Methoden (die dem Benutzer keinen Dialog anzeigen, falls er sich erneut authentifizieren muss) und nicht stumm. Nicht stille Methoden starten im Falle einer erneuten Authentifizierung (oder Zustimmung) des Benutzers eine neue Aktivität, die das AAD-Login enthält. Zu diesem Zeitpunkt wird der Authentifizierungsablauf neu gestartet.

Wenn Sie Änderungen an der Registrierung Ihrer Anwendung in Azure vornehmen, z. B. neue Berechtigungsbereiche hinzufügen, müssen Ihre Benutzer die Zustimmung erneut erteilen, damit die Anwendung ihre Daten weiterhin verarbeiten kann.

2
Brian Melton-Grace - MSFT 6 Jän. 2016 im 22:17

Dies liegt daran, dass Sie Ihr Token aktualisieren und in Ihren Code implementieren müssen, damit der Benutzer nicht jedes Mal aufgefordert wird, sich anzumelden, wenn das Zugriffstoken abgelaufen ist. Hier erfahren Sie, wie Sie das Aktualisierungstoken implementieren:

https://msdn.microsoft.com/en-us/library/azure/dn645538.aspx

Hoffe das hilft.

1
Mostafa 6 Jän. 2016 im 13:47