Функции за ползване на Microsoft Graph

Създаване на проект в администраторския център на Azure Active Directory

Проект трябва да се създаде в администраторския център на Azure Active Directory за потребител с акаунт в MS Office.

Стъпки за създаване на проект в администраторския център на Azure Active Directory

По-долу е стъпка по стъпка ръководство за създаване на проект в администраторския център на Azure Active Directory.

1. Отидете в Azure Active Directory и влезте с вашите MS Office идентификационни данни.

Azure Active Directory Връзка - https://aad.portal.azure.com/

2. Създаване на Azure AD приложение във вашия тенант.

В лявото меню кликнете етикета Azure Active Directory. Това ще отвори панела за Azure Active Directory. На този екран ще видите етикета App registrations. Това е отправната точка за регистриране на Azure AD приложение. Този панел ще ви позволи да създадете ново приложение за Azure AD.

Кликнете върху бутона New registration, за да създадете ново приложение.

todo:image_alt_text

3. Сега ще видите новия панел за регистрация на приложение.

  • Name Това ще бъде името на вашето приложение.
  • Supported account types Този раздел ще ограничи достъпа.

Кликнете бутона Register.

todo:image_alt_text

4. Трябва да видите панела с ново регистрираните приложения.

  • Application (client) ID ID на вашето приложение.
  • Directory (tenant) ID ID на Azure AD тенанта.

todo:image_alt_text

5. Позволяване на разрешения за Microsoft Graph API.

Кликнете върху етикета API permissions.

Azure вече ви е предоставил делегирано разрешение User.Read за вашето приложение. Това разрешение ще ни позволи да четем информация за потребителя, който е влязъл. Това са разрешения за Microsoft Graph API, които можем да наричаме Scopes.

Пълният списък със обхвати (scopes) за Microsoft Graph API - https://docs.microsoft.com/en-us/graph/permissions-reference.

Кликнете бутона + Add a permission и изберете Microsoft Graph.

Кликнете върху Delegated permissions. Сега виждате списък с разрешения, достъпни за Microsoft Graph API.

Изберете необходимите разрешения, кликнете бутона Add permissions.

Кликнете бутона Grant admin consent.

todo:image_alt_text

6. Позволяване на потоци за публичен клиент.

Посочва дали приложението е публичен клиент. Подходящо за приложения, използващи потоци за предоставяне на токени, които не използват пренасочващ URI.

todo:image_alt_text

7. Създаване на ключ за приложението

todo:image_alt_text

Помощни класове

Следните помощни класове са необходими за изпълнението на кода в този раздел. Тези класове служат само за опростяване на демонстрацията.

Клас AzureROPCTokenProvider

Инстанция на IGraphClient класът обработва създаването на заявки, изпращането им към Microsoft Graph API и обработката на отговорите. За да създадете нова инстанция на този клас, трябва да предоставите инстанция на ITokenProvider, който може да удостоверява заявки към Microsoft Graph.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * Azure resource owner password credential (ROPC) token provider
 * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
 * https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
 * https://portal.azure.com
 * https://developer.microsoft.com/en-us/graph/graph-explorer/#
 * token parser https://jwt.io
 * </p>
 */
class AzureROPCTokenProvider implements ITokenProvider {

    private static final String GRANT_TYPE = "password";

    private final String clientId;
    private final String clientSecret;
    private final String userName;
    private final String password;
    private final String tenant;
    private final String scope;

    private OAuthToken token;

    public AzureROPCTokenProvider(String tenant, String clientId, String clientSecret,
                                  String userName, String password, String[] scopeAr) {
        this.tenant = tenant;
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.userName = userName;
        this.password = password;
        this.scope = joinToStr(scopeAr, " ");
    }

    public synchronized OAuthToken getAccessToken(boolean ignoreExistingToken) {
        if (this.token != null && !this.token.getExpired() && !ignoreExistingToken)
            return this.token;
        token = null;

        Map<String, String> tokenArgs = geToken();

        java.util.Calendar c = java.util.Calendar.getInstance();
        c.add(java.util.Calendar.SECOND, Integer.parseInt(tokenArgs.get("expires_in")));
        token = new OAuthToken(tokenArgs.get("access_token"), TokenType.AccessToken, c.getTime());
        return token;
    }

    public final OAuthToken getAccessToken() {
        return getAccessToken(false);
    }

    public void dispose() {
    }

    private String getEncodedParameters() {
        return "client_id=" + urlEncode(clientId) + "&scope=" + urlEncode(scope) + "&username=" + urlEncode(userName)
                + "&password=" + urlEncode(password) + "&grant_type="
                + urlEncode(GRANT_TYPE);
    }

    private String getUri() {
        if (tenant == null || tenant.trim().isEmpty())
            return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
        else
            return "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/token";
    }

    private Map<String, String> geToken() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(getUri()).openConnection();
            connection.setRequestMethod("POST");

            byte[] requestData = getEncodedParameters().getBytes(StandardCharsets.UTF_8);

            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", "" + requestData.length);

            final OutputStream st = connection.getOutputStream();
            try {
                st.write(requestData, 0, requestData.length);
            } finally {
                st.flush();
                st.close();
            }

            connection.connect();

            if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
                throw new IllegalAccessError("Operation failed: " + connection.getResponseCode() + "/" +
                        connection.getResponseMessage() + "\r\nDetails:\r\n{2}"
                        + readInputStream(connection.getErrorStream()));
            }

            String responseText = readInputStream(connection.getInputStream());

            Map<String, String> result = new HashMap<>();
            String[] fromJsonToKeyValue = responseText.replace("{", "").replace("}", "")
                    .replace("\"", "").replace("\r", "")
                    .replace("\n", "").split(",");
            for (String keyValue : fromJsonToKeyValue) {
                String[] pair = keyValue.split(":");
                String name = pair[0].trim().toLowerCase();
                String value = urlDecode(pair[1].trim());
                result.put(name, value);
            }

            return result;
        } catch (IOException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String urlEncode(String value) {
        try {
            return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String urlDecode(String value) {
        try {
            return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String readInputStream(InputStream is) {
        if (is == null)
            return "";

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder result = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }
        } catch (IOException e) {
            // ignore
        }
        return result.toString();
    }

    static String joinToStr(String[] arr, String sep) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            if (i > 0)
                sb.append(sep);
            sb.append(arr[i]);
        }
        return sb.toString();
    }
}