Рубрики
Без рубрики

Безопасные API-интерфейсы с функциями Azure, Java, Azure AD… и MS Graph!

Как разработчику .NET, мне всегда интересно выйти из своей зоны комфорта и поиграть с другими языками и… Помеченный с помощью azure, java, microsoft identity.

Как разработчику .NET, мне всегда интересно выйти из своей зоны комфорта и поиграть с другими языками и фреймворками. Помимо дополнительных знаний и опыта, это также дает вам новый взгляд на то, насколько хороши или плохи ваши любимые инструменты, язык и фреймворки. На этот раз для нашего вторничного Twitch-потока мы решили углубиться в неизведанную территорию и поработать с Java в функциях Azure. И чтобы сделать этот сценарий более полным, я хотел защитить свой Java API с помощью вызова MSAL4J в Azure AD и MS Graph.

Вы можете смотреть весь поток и шаг за шагом

Начало работы с функциями Java и Azure

Опыт разработчиков функций Azure великолепен! Мне нравится, что вы можете разрабатывать и тестировать функции локально с помощью вашей любимой среды разработки (Visual Studio, Visual Studio Code или JetBrains Rider) или даже стандартного текстового редактора и основных инструментов Azure Functions. Для этого потока/блога мы решили использовать VS-код с Java. Однако существуют некоторые дополнительные предварительные условия для того, чтобы иметь возможность работать с функциями Java. Я счел, что лучше всего использовать рекомендации команды в документе “Начало работы”. Однако была упущена одна вещь, и это инструменты ядра функций Azure, которые вам необходимо установить отдельно через NPM или Шоколадный (если вы используете Windows).

Теперь, когда установлено все необходимое программное обеспечение/инструменты, мы можем продолжить и создать нашу функцию Azure с помощью VS Code. Во-первых, мы должны создать папку, которая будет использоваться в качестве нашего рабочего пространства. Вот куда пойдет весь наш функциональный код. Давайте назовем его java-func-auth . В VS Code откройте панель Функции Azure* и нажмите кнопку **Создать новый проект .

Выберите папку, которую мы только что создали, и выберите Java для языка функций:

Выберите все значения по умолчанию и выберите Открыть в текущем окне

Предполагая, что все предварительные требования выполнены, мы можем увидеть, как создается наша функция в окне вывода

На панели Проводника мы разворачиваем папку src , чтобы увидеть фактический код функции. Там есть код основной функции и соответствующий тест. Это приятный штрих от команды Azure Functions, поскольку он помогает нам начать писать надежный, проверяемый код.

Прежде чем мы начнем добавлять какой-либо код, давайте запустим функцию, чтобы убедиться, что все работает так, как ожидалось. Нет смысла двигаться вперед, если ванильный код не запускается из-за отсутствия зависимостей и т.д. VS Code очистит проект, перестроит и запустит нашу функцию Java:

Вы можете использовать curl, Postman или браузер, чтобы попасть в конечную точку функции. URL-адрес по умолчанию – http://localhost:7071/api/HttpExample итак, чтобы получить ответ от нашей функции, нам нужно передать параметр имя . Правильный URL-адрес для использования – http://localhost:7071/api/HttpExample?name=425Show

Возьмите маркер авторизации из заголовка HTTP

Поскольку это должен быть безопасный API, мы ожидаем, что токен будет передан функции через заголовки HTTP-запроса. Имея это в виду, нам нужно написать некоторый код для извлечения токена из заголовка, чтобы мы могли проверить его позже. Давайте создадим новый метод под названием Get Jwt из заголовка() используя приведенный ниже код:

private static String getJwtFromHeader(final HttpRequestMessage> request) {
        final Map headers = request.getHeaders();
        final String authHeader = headers.get("authorization");
        final String[] authHeaderParts = authHeader.split(" ");
        return authHeaderParts[1];
}

Теперь мы должны обновить код основной функции, чтобы извлечь JWT из заголовка и вернуть сообщение об ошибке, если заголовок аутентификации отсутствует

@FunctionName("GetGraphDataForUser")
    public HttpResponseMessage run(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
            HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) final HttpRequestMessage> request,
            final ExecutionContext context) throws Exception {
        context.getLogger().info("Java HTTP trigger processed a request.");

        final String jwt = getJwtFromHeader(request);
        if (jwt == null) {
            return request.createResponseBuilder(HttpStatus.UNAUTHORIZED)
                .body("No Authorization header present")
                .build();
        }
        return request.createResponseBuilder(HttpStatus.OK).body("Well done").build();
    }

Изменение кода функции означает, что наши тесты также необходимо будет обновить, потому что попытка запустить функцию локально сейчас завершится неудачей из-за неудачных тестов. Откройте FunctionTest.java файл и добавьте следующий код:

final Map headers = new HashMap<>();
        headers.put("authorization", "Bearer RandomValue");
        doReturn(headers).when(req).getHeaders();

Давайте запустим нашу функцию и протестируем ее. Поскольку теперь нам нужно передать заголовок авторизации, я переключусь на Postman, чтобы легко протестировать код:

Добавьте библиотеку МАСАЛА

На следующем шаге мы добавим проверку токена и вызов в MS Graph. Чтобы сделать это более простым, корпорация Майкрософт выпустила библиотеку MSAL4J . Поскольку наша функция Java предназначена для работы с Maven, мы можем добавить это как зависимость в наш проект, обновив pom.xml файл со следующим:


    com.microsoft.azure
    msal4j
    1.6.1           

После сохранения файла VS Code предложит нам обновить проект и загрузить зависимости – мне это нравится!

Создайте регистрацию приложений Azure AD

Чтобы иметь возможность проверить ваш токен и вызвать API MS Graph, нам нужно создать пару регистраций приложений в Azure AD . Первая регистрация приложения будет использоваться нашей функцией Azure для проверки токена и вызова MS Graph. Второй будет использоваться нашим клиентским приложением. Клиентом может быть любое приложение, которому необходимо взаимодействовать с нашей функцией Azure аутентифицированным способом.

Создайте регистрацию Java Func API

На портале Azure нам нужно перейти в раздел Azure AD -> Регистрация приложений и создать новую регистрацию приложения: java-func-api . Чтобы предоставить доступ к MS Graph, нам необходимо добавить правильные разрешения в наше приложение. Давайте откроем вкладку Разрешения API , чтобы убедиться, что Microsoft. График->Пользователь. Разрешение на чтение присутствует. Если нет, нам нужно будет добавить его. Также важно предоставить Предоставить согласие администратора , поскольку API не предоставляет интерактивного способа согласия пользователя на эти разрешения. Поэтому нам нужно сделать это заранее:

Нам также необходимо убедиться, что этот API доступен другим клиентским приложениям. Мы делаем это через вкладку Открыть API . Мы настраиваем области, которые клиентские приложения будут запрашивать с помощью кнопки Добавить область . Настройте приложение в соответствии с изображением ниже:

Наконец, нам нужно создать новый Секрет, который мы будем использовать на вкладке Сертификаты и секреты

Запишите секрет, так как вы не сможете получить его снова, как только уйдете. Опять же, вы всегда можете создать новый.

Создайте регистрацию клиента Java Func

Нам также необходимо создать регистрацию приложения для нашего клиентского приложения. Мы будем использовать это с Postman для первой аутентификации в Azure AD, а затем отправлять аутентифицированные запросы в нашу функцию Java.

На портале Azure -> Azure AD -> Регистрация приложения мы регистрируем новое приложение: java-функциональный клиент. Затем нам нужно создать секрет на вкладке Сертификаты и секреты.

Наконец, нам нужно добавить разрешения API в наш java-func-api. В Разрешения API нажмите Добавить разрешение нажмите, а затем выберите Мои API-интерфейсы .

Оттуда выберите java-func-api и добавьте разрешение на регистрацию приложения API функций, которое должно быть access_as_user . Обязательно нажмите кнопку Добавить разрешения в нижней части всплывающей вкладки.

Теперь мы закончили с рекламным порталом Azure.

Использование MSAL4J для проверки токенов и вызова MS Graph

Чтобы выполнить проверку нашего токена и вызвать MS Graph, мы собираемся добавить 2 новых метода в нашу функцию Java: ВалидатеТокен() и Вызовите конечную точку Microsoft Graph() . Код для обоих приведен ниже:

private static IAuthenticationResult ValidateToken(final String authToken) throws Exception {
    final IClientCredential credential = ClientCredentialFactory.createFromSecret(CLIENT_SECRET);
    final ConfidentialClientApplication cca = ConfidentialClientApplication.builder(CLIENT_ID, credential)
                .authority(AUTHORITY).build();
    IAuthenticationResult result;
    try {
        final OnBehalfOfParameters parameters = OnBehalfOfParameters
           .builder(SCOPE, new UserAssertion(authToken)).build();
        result = cca.acquireToken(parameters).join();
    } 
    catch (final Exception ex) {
            throw ex;
    }
    return result;
}

Описанный выше метод создает Конфиденциальное клиентское приложение , которое затем отправляется в AAD и получает токен, чтобы мы могли получить доступ к графику. Если переданный токен аутентификации недействителен/истек срок действия или содержит неправильные области, вызов результат будет ошибкой 401 или 403 соответственно.

private java.net.http.HttpResponse callMicrosoftGraphMeEndpoint(final IAuthenticationResult authResult) throws Exception{
    java.net.http.HttpResponse response = null;
    try {
        java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder()            
           .uri(URI.create("https://graph.microsoft.com/beta/me"))
           .timeout(Duration.ofMinutes(2))
           .header("Content-Type", "application/json")
           .header("Accept", "application/json")
           .header("Authorization", "Bearer " + authResult.accessToken())
           .build();

           final HttpClient client = HttpClient.newHttpClient();
           response = client.send(request, BodyHandlers.ofString());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return response;
}

Описанный выше метод использует токен доступа, который мы только что приобрели, для выполнения аутентифицированного HTTP-вызова MS Graph для получения данных профиля пользователя.

Используйте Пробел + . для устранения всех зависимостей. В верхней части нашего класса нам нужно добавить несколько констант ( private final static в Java) для хранения регистрационной информации нашего приложения Azure AD:

private final static String CLIENT_ID = "84267134-0000-0000-ad1a-6ca96fde3f96";
private final static String AUTHORITY = "https://login.microsoftonline.com/.onmicrosoft.com";
private final static String CLIENT_SECRET = "";
private final static Set SCOPE = Collections.singleton("https://graph.microsoft.com/user.read");

Наконец, нам необходимо обновить наш метод основной функции, чтобы использовать эти два метода для извлечения данных MS Graph для текущего аутентифицированного пользователя с использованием потока OnBehalf:

Замените эту строку:

return request.createResponseBuilder(HttpStatus.OK).body("Well done").build();

С этими 3 строками

final IAuthenticationResult authResult = ValidateToken(jwt);
java.net.http.HttpResponse response = callMicrosoftGraphMeEndpoint(authResult);
return request.createResponseBuilder(HttpStatus.OK).body(response.body()).build();

Примечание: возможно, вы заметили, что нам необходимо полностью определить некоторые переменные. Это связано с тем, что эти объекты существуют как в библиотеках Java util, так и в библиотеках MSAL4J, и нам нужно устранить подобную двусмысленность.

В Postman нам сначала нужно получить новый токен доступа на вкладке “Авторизация”. Используйте этот токен для обновления токена в нашем тестовом коде, потому что в противном случае тесты завершатся неудачей с недопустимым токеном. На данный момент мы хотим только проверить, работает ли наш код, но в конечном итоге нам нужно будет исправить наши тесты, чтобы использовать макет токена.

Сохраните и запустите функцию Java локально с помощью VS Code. Вернувшись в Postman, когда мы отправляем запрос на получение конечной точки функции, мы должны получить наши графические данные, как показано на рисунке.

Резюме

Работа с Azure AD и MS Graph с функциями Java в Azure через MSAL4J проста даже для тех, кто не является опытным разработчиком Java. С помощью нескольких строк кода мы смогли получить токен аутентификации из заголовка входящего запроса, передать его MSAL4J для получения токена доступа, а затем использовать новый токен для вызова MS Graph внутри функции.

Вы можете разветвить и запустить полный образец проекта с GitHub

Оставайтесь на связи!

Мы транслируем прямые трансляции два раза в неделю по адресу twitch.tv/425Show ! Присоединяйтесь к нам:

с 7 утра до 10 утра по тихоокеанскому времени США по вторникам с 8 утра до 9 утра по тихоокеанскому времени США по четвергам для общественных часов

Вы также можете пообщаться с нами на Discord , если у вас есть какие-либо вопросы или вы хотите транслировать с нами на Twitch

До следующего раза, СМ

Оригинал: “https://dev.to/425show/secure-apis-with-azure-functions-java-azure-ad-and-ms-graph-49p1”