0

I am trying to send POST request to Microsoft Azure Graph API for User creation. I have referred their sample example and able to execute GET request successfully but not POST.

My code is as below:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.naming.ServiceUnavailableException;

import org.json.JSONException;
import org.json.JSONObject;

import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;

public class CreateUser {

    private final static String AUTHORITY = "https://login.microsoftonline.com/common/";
    private final static String CLIENT_ID = "<Client_id>";

    public static void main(String args[]) throws Exception {

        try (BufferedReader br = new BufferedReader(new InputStreamReader(
                System.in))) {
            System.out.print("Enter username: ");
            String username = br.readLine();
            System.out.print("Enter password: ");
            String password = br.readLine();

            // Request access token from AAD
            AuthenticationResult result = getAccessTokenFromUserCredentials(
                    username, password);
            // Get user info from Microsoft Graph
            String userInfo = createUserInGraph(result.getAccessToken());
            System.out.print(userInfo);
        }
   }

    private static AuthenticationResult getAccessTokenFromUserCredentials(
            String username, String password) throws Exception {
        AuthenticationContext context;
        AuthenticationResult result;
        ExecutorService service = null;
        try {
            service = Executors.newFixedThreadPool(1);
            context = new AuthenticationContext(AUTHORITY, false, service);
            Future<AuthenticationResult> future = context.acquireToken(
                    "https://graph.microsoft.com", CLIENT_ID, username, password,
                    null);
            result = future.get();
        } finally {
            service.shutdown();
        }

        if (result == null) {
            throw new ServiceUnavailableException(
                    "authentication result was null");
        }
        return result;
    }

    private static String createUserInGraph(String accessToken) throws IOException {

        String jsonInputData = "{  \"accountEnabled\": true," + 
                "  \"city\": \"Delhi\"," + 
                "  \"country\": \"India\"," + 
                "  \"department\": \"Human Resources\"," + 
                "  \"displayName\": \"Adam G\"," + 
                "  \"givenName\": \"Adam\"," + 
                "  \"jobTitle\": \"Senior Human Resource Manager\"," + 
                "  \"mailNickname\": \"adamg\"," + 
                "  \"passwordPolicies\": \"DisablePasswordExpiration\"," + 
                "  \"passwordProfile\": {" + 
                "    \"password\": \"Test1234\"," + 
                "    \"forceChangePasswordNextSignIn\": false" + 
                "  }," + 
                "  \"officeLocation\": \"131/1105\"," + 
                "  \"postalCode\": \"98052\"," + 
                "  \"preferredLanguage\": \"en-US\"," + 
                "  \"state\": \"MH\"," + 
                "  \"streetAddress\": \"9256 Towne Center Dr., Suite 400\"," + 
                "  \"surname\": \"Gily\"," + 
                "  \"mobilePhone\": \"+91 02030713231\"," + 
                "  \"usageLocation\": \"IND\"," + 
                "  \"userPrincipalName\": \"adamg@alandonaldgmail.onmicrosoft.com\"}";

        System.out.println("Input: " + jsonInputData);
        URL url = new URL("https://graph.microsoft.com/v1.0/users");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Authorization", "Bearer " + accessToken);
        System.out.println("Access Token: \n" + accessToken);
        System.out.println();
        conn.setRequestProperty("Content-type","application/json; charset=UTF-8");

        OutputStream os = conn.getOutputStream();
        os.write(jsonInputData.getBytes("UTF-8"));
        os.close();
        //display what returns the POST request

        StringBuilder sb = new StringBuilder();  
        int HttpResult = conn.getResponseCode();
        System.out.println("Response code: " + HttpResult);
        if (HttpResult == HttpURLConnection.HTTP_OK) {
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line = null;  
            while ((line = br.readLine()) != null) {  
                sb.append(line + "\n");  
            }
            br.close();
            System.out.println("" + sb.toString());  
        } else {
            System.out.println(conn.getResponseMessage());  
        }
        return null;
    }
}

So here I am getting error code as 400 and error message as 'Bad request'. Can somebody explain me what is the issue?

Amit Gawali
  • 270
  • 2
  • 4
  • 18

2 Answers2

1

Bad Request issues are usually related to some invalid data/formatting being sent.

Looking at your json, two things stand out. Please make these changes and see if this resolves your issue.

  1. "userPrincipalName": "adamg@alandonaldgmail.onmicrosoft.com" (make sure alandonaldgmail.onmicrosoft.com is a verified domain for your azure active directory organization, if it is not and you used it by mistake, then change the value for userPrincipalName to something like "adamg@yourazureadtenantname.onmicrosoft.com")

  2. "usageLocation": "IND" (this should probably be just "IN", as it's supposed to be a two letter country code (ISO Standard 3166))

Referencing these from here - Update User API Reference

enter image description here

Rohit Saigal
  • 9,317
  • 2
  • 20
  • 32
  • Thank you Rohit, It helps. I tried to create User through code with following json data however it is giving me 400 Bad Request, but I can see that User is getting created in Azure AD, can you tell me what should be the reason? My json data was: `{ "accountEnabled": true, "displayName": "displayName-value", "mailNickname": "mailNickname-value", "userPrincipalName": "adamsg@alandonaldgmail.onmicrosoft.com", "passwordProfile" : { "forceChangePasswordNextSignIn": false, "password": "Sigma@123" } }` – Amit Gawali Sep 19 '18 at 06:24
  • ok, you're using a much smaller json payload this time. I did try out quickly at my end using the same json (changing just userprincipalname to work for my organization) and it worked correctly. 2 things to check: 1. In case of 400, you should be getting some sort of error message back, try to see what is the error 2. One quick guess, I hope you're not trying to create the same UserPrincipalName more than once, because second time onwards it will give you 400 error with "ObjectConflict" code. – Rohit Saigal Sep 19 '18 at 06:37
  • Yes, here are things: 1. Error msg is 'Bad Request' and Error code is 400 2. Yes, I am giving different UserPrincipalName (which is not there) – Amit Gawali Sep 19 '18 at 07:05
  • Do you think there is problem in below code: `URL url = new URL("https://graph.microsoft.com/v1.0/users"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); //conn.setDoInput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Authorization", "Bearer " + accessToken); conn.setRequestProperty("Content-Type","application/json"); OutputStream os = conn.getOutputStream(); os.write(jsonInputData.getBytes("UTF-8"));` – Amit Gawali Sep 19 '18 at 07:06
  • @AmitG is AlanDonaldgmail.onmicrosoft.com a verified domain for your Azure AD? – Rohit Saigal Sep 19 '18 at 07:24
  • yes it is verified domain for my Azure AD. I have created user through Postman also. It is giving 201 Created response but through code it is giving 400 Bad Request but creating user in Azure AD. – Amit Gawali Sep 19 '18 at 07:32
  • @AmitG I have one suggestion, in case you still face issues with different variations of your json data. It will always be tough to know what's exactly causing error until you start seeing more detailed error reason information. So 2 possible things, 1.) try to dig further into the exception object that you get back in code to see if there is something more informative there. 2.) I tried out your exact scenario, not from a Java app, but directly from postman and when my json was not correct, I got detailed error back giving me some hint on what exactly was wrong. So you could try that. – Rohit Saigal Sep 20 '18 at 00:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/180406/discussion-between-amit-g-and-rohit-saigal). – Amit Gawali Sep 20 '18 at 05:56
0

Ok, So I implemented it with HttpClient library. Below is code for the same:

int count = 1;
String jsonInputData = "{ "+
                "  \"accountEnabled\": true," + 
                "  \"displayName\": \"TestUserFromEclipse" +count+"\"," + 
                "  \"mailNickname\": \"mailNickname-value\"," +
                "  \"country\": \"IN\"," +
                "  \"userPrincipalName\": \"eclipseuser"+count+"@alandonaldgmail.onmicrosoft.com\"," + 
                "  \"passwordProfile\" : {" + 
                "    \"forceChangePasswordNextSignIn\": false," + 
                "    \"password\": \"Sigma@123\"" + 
                "  }" + 
                "}";

    HttpPost post = null;
        try {
            String url = "https://graph.microsoft.com/v1.0/users";
            StringEntity s = new StringEntity(jsonInputData);
            HttpClient client = HttpClientBuilder.create().build();
            post = new HttpPost(url);

            // add header
            post.setHeader("Content-Type", "application/json");
            post.setHeader("Authorization", "Bearer " + accessToken);
            post.setEntity(s);

            HttpResponse response = client.execute(post);
            System.out.println("Response Code : " 
                        + response.getStatusLine().getStatusCode());
        } finally {
            post.releaseConnection();
        }
Amit Gawali
  • 270
  • 2
  • 4
  • 18