Проверка подлинности OneDrive с использованием ADAL4J

Библиотека проверки подлинности Active Directory для Java (ADAL4J) позволяет выполнять проверку подлинности через доступ в API Microsoft Graph, используя следующий (упрощенный) код:

public String authenticate(String authorizationUrl, String clientId, String clientSecret) throws Exception {
    ExecutorService service = Executors.newFixedThreadPool(1);
    AuthenticationContext context = new AuthenticationContext(authorizationUrl, false, service);
    ClientCredential credential = new ClientCredential(clientId, clientSecret);
    Future<AuthenticationResult> future = context.acquireToken(“https://graph.microsoft.com”, credential, null);
    return future.get().getAccessToken();
}

Вышеупомянутое работает для определенных частей Graph (например, для доступа к Office 365 учетным записям), но не работает для OneDrive, где он возвращает токен доступа, который не имеет надлежащей авторизации.

Получение маркера доступа через POSTMAN работает, как и ожидалось, со следующими параметрами:

authorizationUrl: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
accessTokenUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token
clientId: <the clientId for the application>
clientSecret: <the clientSecret for the application> 
scope: https://graph.microsoft.com/.default
state: <empty>

В частности, выполнение вышеописанного в POSTMAN возвращает токен доступа с дополнительными областями действия, включая https://graph.microsoft.com/Files.ReadWrite.All. Использование этого токена доступа в приложении Java, которое вызывает описанный выше метод authenticate(), действительно работает, например. он перечисляет содержимое корневого каталога, используя /me/drive/root/children в качестве пути REST.

Однако если используется токен доступа, возвращаемый методом authenticate(), OneDrive возвращает ошибку. Удаление имени пользователя (me) из пути возвращает только 1 имя файла, если вместо common в авторизацииUrl используется конкретный идентификатор арендатора.

Кажется, что нет способа добавить значение области действия в ADAL4J, а многочисленные другие варианты приводят либо к ошибке, либо к возврату 1 файла (вероятно, из другого контекста).

Есть ли способ получить полностью авторизованный токен доступа через ADAL4J для OneDrive?


person PNS    schedule 31.07.2019    source источник


Ответы (1)


Существует два разных разрешения: одно — разрешение приложения, другое — делегированное разрешение.

"Делегированные" разрешения, определяющие доступ на основе области с использованием делегированной авторизации от вошедшего в систему владельца ресурса, представляются ресурсу во время выполнения как утверждения "scp" в маркере доступа клиента.

Разрешения «приложения», которые определяют доступ на основе ролей с использованием учетных данных/идентификатора клиентского приложения, представляются ресурсу во время выполнения в виде утверждений «ролей» в маркере доступа клиента.

Когда вы впервые получите токен от POSTMAN, вам будет предложено предоставить свои учетные данные. Таким образом, вы получите токен с делегированным разрешением, который представляет учетную запись. Таким образом, вы можете вызывать Graph API из /me.

Однако код Java, который вы использовали для получения токена, может получить токен доступа только с разрешением приложения. Приложение не имеет удостоверения пользователя, в результате вы получите сообщение об ошибке при вызове Graph API под /me. С разрешением приложения вы можете вызывать Graph API только как /users/{user-id}

Решение:

Вы можете получить токен доступа с делегированным разрешением в Java следующим образом:

A) Создайте приложение с общедоступной клиентской платформой

введите здесь описание изображения

Б) Добавьте необходимое разрешение Graph API и предоставьте согласие администратора для вашего клиента.

введите здесь описание изображения

В) Получить токен

ExecutorService service = Executors.newFixedThreadPool(1);
AuthenticationContext context = null;
try {
    context = new AuthenticationContext("https://login.microsoftonline.com/" + "TENANT_ID", false, service);
    Future<AuthenticationResult> future = context.acquireToken("https://graph.microsoft.com", "client_id", "username", "password",null);
    System.out.println( future.get().getAccessToken());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
} catch (MalformedURLException e) {
    e.printStackTrace();
}finally {
    service.shutdown();
}
person Jack Jia    schedule 02.08.2019
comment
Я сделал все это в различных комбинациях, включая «Предоставить согласие администратора». Во всяком случае, я попытался еще раз с URL-адресом авторизации, который имеет определенный tenantId (вместо «общий», хотя я также пробовал это), для того же приложения, используя тот же clientId и clientSecret (вместо имени пользователя и пароля) в Метод аутентификации (), который я разместил выше, и он работает. Не уверен, что происходит, но вы заслуживаете большей части похвалы, поэтому +1 и принятый ответ. Спасибо! :-) - person PNS; 03.08.2019
comment
Проблема заключалась в том, что общий арендатор ссылается на другой диск, чем конкретный арендатор, отсюда и несоответствие результатов. - person PNS; 04.08.2019