0

I am trying to get Azure AD user Attribute CompanyName using user id, passwor, client id, and Tenant Id using java.

Reffered this Doc: <https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=java> under username/password provider.

My Azure AD setup:

  1. in azure ad, ive created a user with company name property.
  2. Created Azure App registration, with localhost redirect URI & marked on id tokens under authetication section,
  • created Client secret,
  • Added role for App registration, added user to app regisitrion with that role under enterprise application.
  • i've used client id, tenent id, user id, password correctly also tested these credentials with spring boot project there it is working fine (able to access comapnyName) after Login (SSO), but my requirement is i need to fetch user comapy details without SSO, for api use case.

here is my java code:

import java.util.Arrays;
import java.util.List;

import com.azure.identity.UsernamePasswordCredential;
import com.azure.identity.UsernamePasswordCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.User;
import com.microsoft.graph.requests.GraphServiceClient;


public class azureADUserAuth {
    final String clientId = "YOUR_CLIENT_ID";
    final String tenantId = "YOUR_TENANT_ID"; // or "common" for multi-tenant apps
    final String userName = "YOUR_USER_NAME";
    final String password = "YOUR_PASSWORD";
    final List<String> scopes = Arrays.asList("User.Read"); 

    public static void main (String[] args) {
        try {
UsernamePasswordCredential credential = new UsernamePasswordCredentialBuilder()
    .clientId(clientId).tenantId(tenantId).username(userName).password(password)
    .build();

    if (null == scopes || null == credential) {
            throw new Exception("Unexpected error");
        }
    TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(scopes,credential);
GraphServiceClient graphClient = GraphServiceClient .builder() .authenticationProvider(authProvider) .buildClient();
    
    User me = graphClient.me().buildRequest().get();
    System.out.println(me.companyName);
   }catch (Exception e) {
        e.printStackTrace();
    }

here code printing 5 errors in console

  1. com.microsoft.graph.core.ClientException: Error executing the request
  2. Caused by: java.io.IOException: java.util.concurrent.ExecutionException: com.azure.core.exception.ClientAuthenticationException: Failed to acquire token with username and password
  3. Caused by: java.util.concurrent.ExecutionException: com.azure.core.exception.ClientAuthenticationException: Failed to acquire token with username and password
  4. Caused by: com.azure.core.exception.ClientAuthenticationException: Failed to acquire token with username and password
  5. Caused by: com.microsoft.aad.msal4j.MsalServiceException: AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'. Trace ID: 8e0854e2-6d51-422e-b2d5-47b6303b2400 Correlation ID: 5df6d392-3bcb-4730-9666-4ae8f9131681 Timestamp: 2023-08-18 18:00:51Z

Please Help!

Balu
  • 9
  • 5
  • You need to either include `client_Secret` parameter in your code or enable **public client flows** option like [this](https://i.imgur.com/mdfUYbO.png). – Sridevi Aug 19 '23 at 05:03
  • Hi sridevi, thanks it's working now. But I need to get companyname attribute for this I have added user.companyname under oidc based sign on but still iam getting null value with S.O.P(me.companyName); why? Any idea ? – Balu Aug 19 '23 at 09:52
  • You need to use `$select` query to fetch companyName like this: `User user = graphClient.me().buildRequest().select("companyName").get();` – Sridevi Aug 19 '23 at 09:58
  • 1
    Thanks! Sridevi, It's working fine – Balu Aug 19 '23 at 10:46

1 Answers1

0

When I tried to generate access token using username password flow via Postman without passing client_secret, I got same error as below:

POST https://login.microsoftonline.com/tenantId/oauth2/v2.0/token
client_id:appId
grant_type:password
scope:User.Read
username:sri@xxxxxxxx.onmicrosoft.com
password:xxxxxxxxxx

Response:

enter image description here

To resolve the error, you need to either include client_secret parameter in your code or enable public client flow option.

In my case, I enabled public client flow option in my Azure AD application like this:

enter image description here

After enabling public client flows option, I am able to get access token without including client_secret parameter:

POST https://login.microsoftonline.com/tenantId/oauth2/v2.0/token
client_id:appId
grant_type:password
scope:User.Read
username:sri@xxxxxxxx.onmicrosoft.com
password:xxxxxxxxxx

Response:

enter image description here

You can decode the above token in jwt.ms website to check permissions in scp claim:

enter image description here

When I used this token to call /me endpoint, I too did n't get companyName property in response like below:

GET https://graph.microsoft.com/v1.0/me

Response:

enter image description here

Note that, only limited properties are returned by /me endpoint by default. To get specific properties like companyName in response, you need to use $select query parameter in graph call.

When I ran below query with $select parameter, I got companyName in response successfully:

GET https://graph.microsoft.com/v1.0/me?$select=companyName

Response:

enter image description here

To confirm that, I checked the same in Portal where user's company Name attribute value is same as below:

enter image description here

Sample java code:

GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( authProvider ).buildClient();

User me = graphClient.me()
    .buildRequest()
    .select("companyName")
    .get();

System.out.println(me.companyName);
Sridevi
  • 10,599
  • 1
  • 4
  • 17