From 77e2a1038958530bf596a754fee0b6592845c337 Mon Sep 17 00:00:00 2001 From: Jason Johnston Date: Tue, 16 Mar 2021 15:24:14 -0400 Subject: [PATCH 1/3] Updated to v3 of the Graph SDK Made required code changes and updated tutorial --- demo/graphtutorial/build.gradle | 5 +- .../src/main/java/graphtutorial/App.java | 30 +++--- .../java/graphtutorial/Authentication.java | 80 ---------------- .../src/main/java/graphtutorial/Graph.java | 92 ++++++++++++------- .../graphtutorial/SimpleAuthProvider.java | 31 ------- tutorial/02-create-app.md | 5 +- tutorial/04-add-aad-auth.md | 79 +++++++++++++++- tutorial/05-add-ms-graph.md | 86 ++--------------- tutorial/06-create-event.md | 2 +- 9 files changed, 159 insertions(+), 251 deletions(-) delete mode 100644 demo/graphtutorial/src/main/java/graphtutorial/Authentication.java delete mode 100644 demo/graphtutorial/src/main/java/graphtutorial/SimpleAuthProvider.java diff --git a/demo/graphtutorial/build.gradle b/demo/graphtutorial/build.gradle index d45faba..b53ad8f 100644 --- a/demo/graphtutorial/build.gradle +++ b/demo/graphtutorial/build.gradle @@ -27,9 +27,8 @@ dependencies { // Use JUnit test framework testImplementation 'junit:junit:4.12' - implementation 'com.microsoft.azure:msal4j:1.8.0' - implementation 'com.microsoft.graph:microsoft-graph:2.4.1' - implementation 'org.slf4j:slf4j-nop:1.8.0-beta4' + implementation 'com.azure:azure-identity:1.2.3' + implementation 'com.microsoft.graph:microsoft-graph:3.0.0' } // diff --git a/demo/graphtutorial/src/main/java/graphtutorial/App.java b/demo/graphtutorial/src/main/java/graphtutorial/App.java index f18488d..dc80206 100644 --- a/demo/graphtutorial/src/main/java/graphtutorial/App.java +++ b/demo/graphtutorial/src/main/java/graphtutorial/App.java @@ -13,15 +13,16 @@ import java.time.format.FormatStyle; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAdjusters; +import java.util.Arrays; import java.util.HashSet; import java.util.InputMismatchException; import java.util.List; import java.util.Properties; import java.util.Scanner; -import com.microsoft.graph.models.extensions.DateTimeTimeZone; -import com.microsoft.graph.models.extensions.Event; -import com.microsoft.graph.models.extensions.User; +import com.microsoft.graph.models.DateTimeTimeZone; +import com.microsoft.graph.models.Event; +import com.microsoft.graph.models.User; /** * Graph Tutorial @@ -43,15 +44,16 @@ public static void main(String[] args) { } final String appId = oAuthProperties.getProperty("app.id"); - final String[] appScopes = oAuthProperties.getProperty("app.scopes").split(","); + final List appScopes = Arrays + .asList(oAuthProperties.getProperty("app.scopes").split(",")); // - // Get an access token - Authentication.initialize(appId); - final String accessToken = Authentication.getUserAccessToken(appScopes); + // Initialize Graph with auth settings + Graph.initializeGraphAuth(appId, appScopes); + final String accessToken = Graph.getUserAccessToken(); // Greet the user - User user = Graph.getUser(accessToken); + User user = Graph.getUser(); System.out.println("Welcome " + user.displayName); System.out.println("Time zone: " + user.mailboxSettings.timeZone); System.out.println(); @@ -87,11 +89,11 @@ public static void main(String[] args) { break; case 2: // List the calendar - listCalendarEvents(accessToken, user.mailboxSettings.timeZone); + listCalendarEvents(user.mailboxSettings.timeZone); break; case 3: // Create a new event - createEvent(accessToken, user.mailboxSettings.timeZone, input); + createEvent(user.mailboxSettings.timeZone, input); break; default: System.out.println("Invalid choice"); @@ -112,7 +114,7 @@ private static String formatDateTimeTimeZone(DateTimeTimeZone date) { // // - private static void listCalendarEvents(String accessToken, String timeZone) { + private static void listCalendarEvents(String timeZone) { ZoneId tzId = GraphToIana.getZoneIdFromWindows("Pacific Standard Time"); // Get midnight of the first day of the week (assumed Sunday) @@ -126,7 +128,7 @@ private static void listCalendarEvents(String accessToken, String timeZone) { ZonedDateTime endOfWeek = startOfWeek.plusDays(7); // Get the user's events - List events = Graph.getCalendarView(accessToken, + List events = Graph.getCalendarView( startOfWeek, endOfWeek, timeZone); System.out.println("Events:"); @@ -143,7 +145,7 @@ private static void listCalendarEvents(String accessToken, String timeZone) { // // - private static void createEvent(String accessToken, String timeZone, Scanner input) { + private static void createEvent(String timeZone, Scanner input) { DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M/d/yyyy h:mm a"); // Prompt for subject @@ -218,7 +220,7 @@ private static void createEvent(String accessToken, String timeZone, Scanner inp System.out.print("Is this correct? (y/n): "); if (input.nextLine().trim().toLowerCase().startsWith("y")) { - Graph.createEvent(accessToken, timeZone, subject, start, end, attendees, body); + Graph.createEvent(timeZone, subject, start, end, attendees, body); System.out.println("Event created."); } else { System.out.println("Canceling."); diff --git a/demo/graphtutorial/src/main/java/graphtutorial/Authentication.java b/demo/graphtutorial/src/main/java/graphtutorial/Authentication.java deleted file mode 100644 index d13a806..0000000 --- a/demo/graphtutorial/src/main/java/graphtutorial/Authentication.java +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// -package graphtutorial; - -import java.net.MalformedURLException; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.function.Consumer; - -import com.microsoft.aad.msal4j.DeviceCode; -import com.microsoft.aad.msal4j.DeviceCodeFlowParameters; -import com.microsoft.aad.msal4j.IAuthenticationResult; -import com.microsoft.aad.msal4j.PublicClientApplication; - -/** - * Authentication - */ -public class Authentication { - - private static String applicationId; - // Set authority to allow only organizational accounts - // Device code flow only supports organizational accounts - private final static String authority = "https://login.microsoftonline.com/common/"; - - public static void initialize(String applicationId) { - Authentication.applicationId = applicationId; - } - - public static String getUserAccessToken(String[] scopes) { - if (applicationId == null) { - System.out.println("You must initialize Authentication before calling getUserAccessToken"); - return null; - } - - Set scopeSet = Set.of(scopes); - - ExecutorService pool = Executors.newFixedThreadPool(1); - PublicClientApplication app; - try { - // Build the MSAL application object with - // app ID and authority - app = PublicClientApplication.builder(applicationId) - .authority(authority) - .executorService(pool) - .build(); - } catch (MalformedURLException e) { - return null; - } - - // Create consumer to receive the DeviceCode object - // This method gets executed during the flow and provides - // the URL the user logs into and the device code to enter - Consumer deviceCodeConsumer = (DeviceCode deviceCode) -> { - // Print the login information to the console - System.out.println(deviceCode.message()); - }; - - // Request a token, passing the requested permission scopes - IAuthenticationResult result = app.acquireToken( - DeviceCodeFlowParameters - .builder(scopeSet, deviceCodeConsumer) - .build() - ).exceptionally(ex -> { - System.out.println("Unable to authenticate - " + ex.getMessage()); - return null; - }).join(); - - pool.shutdown(); - - if (result != null) { - return result.accessToken(); - } - - return null; - } -} -// \ No newline at end of file diff --git a/demo/graphtutorial/src/main/java/graphtutorial/Graph.java b/demo/graphtutorial/src/main/java/graphtutorial/Graph.java index 306fadb..56a809b 100644 --- a/demo/graphtutorial/src/main/java/graphtutorial/Graph.java +++ b/demo/graphtutorial/src/main/java/graphtutorial/Graph.java @@ -3,6 +3,7 @@ package graphtutorial; +import java.net.URL; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -10,51 +11,72 @@ import java.util.List; import java.util.Set; +import okhttp3.Request; + +import com.azure.identity.DeviceCodeCredential; +import com.azure.identity.DeviceCodeCredentialBuilder; + +import com.microsoft.graph.authentication.TokenCredentialAuthProvider; import com.microsoft.graph.logger.DefaultLogger; import com.microsoft.graph.logger.LoggerLevel; -import com.microsoft.graph.models.extensions.Attendee; -import com.microsoft.graph.models.extensions.DateTimeTimeZone; -import com.microsoft.graph.models.extensions.EmailAddress; -import com.microsoft.graph.models.extensions.Event; -import com.microsoft.graph.models.extensions.IGraphServiceClient; -import com.microsoft.graph.models.extensions.ItemBody; -import com.microsoft.graph.models.extensions.User; -import com.microsoft.graph.models.generated.AttendeeType; -import com.microsoft.graph.models.generated.BodyType; +import com.microsoft.graph.models.Attendee; +import com.microsoft.graph.models.DateTimeTimeZone; +import com.microsoft.graph.models.EmailAddress; +import com.microsoft.graph.models.Event; +import com.microsoft.graph.models.ItemBody; +import com.microsoft.graph.models.User; +import com.microsoft.graph.models.AttendeeType; +import com.microsoft.graph.models.BodyType; import com.microsoft.graph.options.HeaderOption; import com.microsoft.graph.options.Option; import com.microsoft.graph.options.QueryOption; -import com.microsoft.graph.requests.extensions.GraphServiceClient; -import com.microsoft.graph.requests.extensions.IEventCollectionPage; -import com.microsoft.graph.requests.extensions.IEventCollectionRequestBuilder; +import com.microsoft.graph.requests.GraphServiceClient; +import com.microsoft.graph.requests.EventCollectionPage; +import com.microsoft.graph.requests.EventCollectionRequestBuilder; /** * Graph */ public class Graph { - private static IGraphServiceClient graphClient = null; - private static SimpleAuthProvider authProvider = null; + private static GraphServiceClient graphClient = null; + private static TokenCredentialAuthProvider authProvider = null; + + @SuppressWarnings("unchecked") + public static void initializeGraphAuth(String applicationId, List scopes) { + // Create the auth provider + final DeviceCodeCredential credential = new DeviceCodeCredentialBuilder() + .clientId(applicationId) + .challengeConsumer(challenge -> System.out.println(challenge.getMessage())) + .build(); - private static void ensureGraphClient(String accessToken) { - if (graphClient == null) { - // Create the auth provider - authProvider = new SimpleAuthProvider(accessToken); + authProvider = new TokenCredentialAuthProvider(scopes, credential); - // Create default logger to only log errors - DefaultLogger logger = new DefaultLogger(); - logger.setLoggingLevel(LoggerLevel.ERROR); + // Create default logger to only log errors + DefaultLogger logger = new DefaultLogger(); + logger.setLoggingLevel(LoggerLevel.ERROR); - // Build a Graph client - graphClient = GraphServiceClient.builder() - .authenticationProvider(authProvider) - .logger(logger) - .buildClient(); + // Build a Graph client + graphClient = GraphServiceClient.builder() + .authenticationProvider(authProvider) + .logger(logger) + .buildClient(); + } + + public static String getUserAccessToken() + { + try { + URL meUrl = new URL("https://graph.microsoft.com/v1.0/me"); + return authProvider.getAuthorizationTokenAsync(meUrl).get(); + } catch(Exception ex) { + return null; } } - public static User getUser(String accessToken) { - ensureGraphClient(accessToken); + // + public static User getUser() { + if (graphClient == null) throw new NullPointerException( + "Graph client has not been initialized. Call initializeGraphAuth before calling this method"); // GET /me to get authenticated user User me = graphClient @@ -65,11 +87,13 @@ public static User getUser(String accessToken) { return me; } + // // - public static List getCalendarView(String accessToken, + public static List getCalendarView( ZonedDateTime viewStart, ZonedDateTime viewEnd, String timeZone) { - ensureGraphClient(accessToken); + if (graphClient == null) throw new NullPointerException( + "Graph client has not been initialized. Call initializeGraphAuth before calling this method"); List