[Java] Use Microsoft Graph with standard Java

4 minute read

Microsoft Graph in standard Java package

You can use the Microsoft SDK for Java, but it requires a lot of related Jar files. To understand what you’re doing in essence, let’s write a Microsoft Graph query with just a standard Java package.

What to do

  1. Register the application in Azure AD and create a client ID and secret (the procedure is Tutorial. reference)
  2. Get an access token from Azure AD with OAuth2. It will be returned in JSON.
  3. Contact the Microsoft Graph API endpoint. JSON is returned.
    only.

If you write it with the Curl command for the time being, it will be like this

Get an access token.

First, get an access token from Azure Active Directory according to the OAuth procedure.
The URL (endpoint) to get is

** https://login.microsoftonline.com/tenant ID/oauth2/v2.0/token **

The tenant ID can be found in the Azure AD tenant overview.
POST the client ID and secret created towards here.
Since scope escapes the URL, it is% 3A or% 2F. For details on what can be specified, click here [https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-permissions-and-consent). grant_type is an OAuth parameter with a fixed value.

curl -d "client_id=Client ID" \
 -d "scope=https%3A%2F%2Fgraph.microsoft.com%2F.default" \
 -d "client_secret=Client secret" \
 -d "grant_type=client_credentials" \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -X POST https://login.microsoftonline.com/Tenant ID/oauth2/v2.0/token

You can get an access token.
image.png

Contact the Microsoft Graph API using an access token

Copy the previous access token and now query and manipulate the Microsoft Graph API. For example, if you want to get a group member, it will look like this.
Click here for the endpoint.

https://graph.microsoft.com/v1.0/groups/{group-id}/members

Use Graph Explorer to check where the endpoint is and the format.
I will omit it, but for the group ID, I logged in to Azure AD and obtained the ID displayed in the “All groups” list in advance.

curl -H GET 'https://graph.microsoft.com/v1.0/groups/Group ID/members'\
 -H 'Content-Type: application/json;charset=utf-8'\
 -H 'Authorization:Bearer access token'

I’ve omitted the screenshot of the result, but you can see that the value is returned in JSON format.
image.png

If you write this HTTP process in Java

This time it is written in Java 8.
Also, error handling is omitted. If the network is under a proxy, set the proxy settings using Java environment variables.

App.java


import java.io.*;
import java.net.*;

//Although it is said to be a standard package, I used the javax additional library only here.
//It also decodes Unicode escaped characters
//Click here for Jar file
//https://repo1.maven.org/maven2/org/glassfish/javax.json/1.1.4/javax.json-1.1.4.jar
import javax.json.*;

public class App {

	public static void main(String[] args) throws Exception {
		
		String tenant_id = "Tenant ID";
		String client_id = "Client ID";
		String client_secret = "Client secret";
		String group_id = "Group ID";
		
		HttpURLConnection conn = null;
		InputStream input = null;
		HttpURLConnection conn2 = null;
		InputStream input2 = null;
		try {
			//①
			//Get an access token with Oauth2
			
			//Java standard HTTP request processing
			URL url = new URL("https://login.microsoftonline.com/" + tenant_id + "/oauth2/v2.0/token");
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);//Time to connect millisecond
			conn.setReadTimeout(5000);//Time to read data milliseconds
			conn.setRequestMethod("POST");//HTTP method
			conn.setUseCaches(false);//Use cache
			conn.setDoOutput(true);//Allow sending of request body(False for GET,Set to true for POST)
			conn.setDoInput(true);//Allow receiving body of response
			conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			String data = //Data to post
				  "client_id=" + client_id
				+ "&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default"  //java.net.May be escaped with URLEncoder
				+ "&client_secret=" + client_secret
				+ "&grant_type=client_credentials";
			conn.getOutputStream().write(data.getBytes("utf-8"));
			conn.getOutputStream().close(); // send
			
			//Receive the result and convert it to a Json object
			//If you don't use the JSON library, just parse the returned text on your own
			//I'm getting something similar to the string I was getting with Curl
			int code = conn.getResponseCode();
			input = (code == 200 ? conn.getInputStream() : conn.getErrorStream());
			JsonReader jsonReader = Json.createReader(new BufferedReader(new InputStreamReader(input, "utf-8")));
			JsonObject json = jsonReader.readObject();
			jsonReader.close();
			conn.disconnect();
			
			//I got the access token!
			String access_token = json.getString("access_token");
			
			
			//②
			//Next, contact the Microsoft Graph API for group members
			URL url2 = new URL("https://graph.microsoft.com/v1.0/groups/" + group_id + "/members");
			conn2 = (HttpURLConnection) url2.openConnection();
			conn2.setConnectTimeout(5000);//Time to connect millisecond
			conn2.setReadTimeout(5000);//Time to read data milliseconds
			conn2.setRequestMethod("GET");
			conn2.setUseCaches(false);//Use cache
			conn2.setDoOutput(false);//Allow sending of request body(False for GET,Set to true for POST)
			conn2.setDoInput(true);//Allow receiving body of response
			conn2.setRequestProperty("Authorization", "Bearer " + access_token); //Obtained access token
			conn2.setRequestProperty("Accept", "application/json"); //This is important! !! !! The point I was addicted to
			conn2.connect();
		
			int code2 = conn2.getResponseCode();
			input2 = (code2 == 200 ? conn2.getInputStream() : conn2.getErrorStream());
			JsonReader jsonReader2 = Json.createReader(new BufferedReader(new InputStreamReader(input2, "utf-8")));
			JsonStructure json2 = jsonReader2.read();
			jsonReader2.close();
			conn2.disconnect();
		
			JsonArray members = json2.asJsonObject().getJsonArray("value");
			
			//I got a member of the group!
			System.out.println(members);
		}
		catch(Error e) {
			e.printStackTrace();
		}
		finally {
			if(input != null) try { input.close(); } catch(Exception e){}
			if(conn != null) try { conn.disconnect(); } catch(Exception e){}
			if(input2 != null) try { input2.close(); } catch(Exception e){}
			if(conn2 != null) try { conn2.disconnect(); } catch(Exception e){}
		}
	}
}

I got it properly when I compiled and executed it.
image.png

Summary

Simple acquisition is possible without using the SDK, you can grasp the essence because you do not need multiple additional Jar files and the procedure with the server is not hidden.
On the other hand, if you use the SDK, you can concentrate on coding without being aware of the token expiration or the URL of the endpoint, and Graph Explorer will output a code snippet, so I think that productivity will increase.