0
votes

I have done a single tenant Authentication which works fine for me. Now I am changing the app to multi tenant authentication. I have changed the app from single tenant to multi-tenant in azure. But I am not able to find any code for multi tenant authentication in Java. What all changes I will have to make to the following code to make it work for multi tenant authentication. Code :-

private String getAccessToken() {
    String accessToken = "";
    try {
        ExecutorService service = Executors.newFixedThreadPool(1); 
        String authorization_url = "https://login.microsoftonline.com/" + Authentication_Constants.TENANT + "/oauth2/authorize/";
        AuthenticationContext authContext = new AuthenticationContext(authorization_url, false, service);
        ClientCredential clientCred = new ClientCredential(Authentication_Constants.CLIENTID, Authentication_Constants.SECRET);
        Future<AuthenticationResult>  future = authContext.acquireToken(Authentication_Constants.RESOURCE, clientCred, null);
        AuthenticationResult authResult = future.get(); 
        accessToken = authResult.getAccessToken();
    } catch (Exception ex) {
        System.out.println(ex.getLocalizedMessage());
    }
    return accessToken;
}

Update :- I changed the authorization url to https://login.microsoftonline.com/common/oauth2/authorize/ which does gives me access token.For a multi-tenant application, the initial registration for the application lives in the Azure AD tenant used by the developer. When a user from a different tenant signs in to the application for the first time, Azure AD asks them to consent to the permissions requested by the application. If they consent, then a representation of the application called a service principal is created in the user’s tenant, and sign-in can continue. How can I get consent without providing UI as I already have user's credentials? How to plug those things in my current code to get access token for different tenant?

Update 2:- I tried to use the following api for authentication :- authContext.acquireToken(Authentication_Constants.RESOURCE, Authentication_Constants.CLIENTID, "username", Authentication_Constants.password, null); But I came to know its not supported. And get following exception :- "error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'. So I am pretty lost in this multi tenant authentication.

Note :- Instead of going to the sign in page of Microsoft, I can provide user credentials which will have set of permissions for my web app to access or like default permissions. Can anyone please suggest something? Thanks!

1

1 Answers

2
votes

What you are asking for cannot be done.

The API you tried to use (which complained about missing client secret) is the ROPC flow. It cannot do consent.

In order to do consent, the user must get into a web browser, go to the authorization endpoint, and authorize your app to access in their directory.

The point, as I see it, is so that someone with your username and password cannot just give permissions to whatever they want. It must be the user saying that these things are okay. They should never have to give their password to your app anyway.

If your app cannot provide the web browser UI, one way would be to use device code authentication. Sample here for .NET: https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-deviceprofile/.

In the device code flow, you request the user to open a browser and navigate to a short URL. Then they must enter the code shown to them and then they can do consent in the browser. Your app would have to poll the endpoint to know when it is done.

Sadly, it seems Adal4J does not offer this API yet. It is available in the .NET version though: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/blob/dev/adal/src/Microsoft.IdentityModel.Clients.ActiveDirectory/AuthenticationContext.cs#L174.