Funkcje pomocnicze Microsoft Graph

Tworzenie projektu w centrum administracyjnym Azure Active Directory

Projekt należy utworzyć w centrum administracyjnym Azure Active Directory dla użytkownika posiadającego konto MS Office.

Kroki tworzenia projektu w centrum administracyjnym Azure Active Directory

Poniżej znajdziesz krok po kroku tutorial tworzenia projektu w centrum administracyjnym Azure Active Directory.

1. Przejdź do Azure Active Directory i zaloguj się używając swoich poświadczeń MS Office.

Azure Active Directory Link - https://aad.portal.azure.com/

2. Utwórz aplikację Azure AD w swoim dzierżawcy.

W lewym panelu kliknij etykietę Azure Active Directory. Otworzy to panel Azure Active Directory. Na tym ekranie powinieneś zobaczyć etykietę App registrations. To punkt początkowy rejestracji aplikacji Azure AD. Ten panel pozwoli Ci utworzyć nową aplikację w Azure AD.

Kliknij przycisk New registration, aby utworzyć nową aplikację.

todo:image_alt_text

3. Teraz zobaczysz panel rejestracji nowej aplikacji.

  • Name To będzie nazwa Twojej aplikacji.
  • Supported account types Ta sekcja ograniczy dostęp.

Kliknij przycisk Register.

todo:image_alt_text

4. Powinieneś zobaczyć panel nowo zarejestrowanych aplikacji.

  • Application (client) ID Identyfikator Twojej aplikacji.
  • Directory (tenant) ID Identyfikator dzierżawcy Azure AD.

todo:image_alt_text

5. Zezwalanie na uprawnienia dla Microsoft Graph API.

Kliknij etykietę API permissions.

Azure już przyznało Twojej aplikacji delegowane uprawnienie User.Read. To uprawnienie pozwala odczytać informacje o zalogowanym użytkowniku. Są to uprawnienia Microsoft Graph API, które w innym kontekście nazywamy zakresami.

Pełna lista zakresów (scopes) dla Microsoft Graph API - https://docs.microsoft.com/en-us/graph/permissions-reference.

Kliknij przycisk + Add a permission i wybierz Microsoft Graph.

Kliknij Delegated permissions. Teraz widzisz listę dostępnych uprawnień dla Microsoft Graph API.

Wybierz wymagane uprawnienia, kliknij przycisk Add permissions.

Kliknij przycisk Grant admin consent.

todo:image_alt_text

6. Zezwalaj na przepływy klientów publicznych.

Określa, czy aplikacja jest klientem publicznym. Odpowiednie dla aplikacji używających przepływów tokenów, które nie korzystają z URI przekierowania.

todo:image_alt_text

7. Utwórz klucz dla aplikacji

todo:image_alt_text

Klasy pomocnicze

Poniższe klasy pomocnicze są wymagane do uruchomienia kodu w tej sekcji. Służą one wyłącznie uproszczeniu demonstracji.

Klasa AzureROPCTokenProvider

Instancja IGraphClient klasa obsługuje budowanie żądań, ich wysyłanie do API Microsoft Graph oraz przetwarzanie odpowiedzi. Aby stworzyć nową instancję tej klasy, musisz dostarczyć instancję ITokenProvider, które mogą uwierzytelniać żądania do 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();
    }
}