Hot questions for Using Azure in azure ad graph api

Top Java Programmings / Azure / azure ad graph api

Question:

I am a reasonably experienced Java developer (4-5 years) but new to Azure AD and its capabilities, so I apologize in advance for a potentially basic question. I have struggled to find any Microsoft documentation or Stack Overflow questions covering this topic in Java (vast majority being in C#) and from my understanding, C# has more Azure AD libraries than Java, hence the solution in C# will not necessarily be the solution in Java.

I am trying to complete a authentication POC based on a scenario in-which there is an existing Azure AD system, full of users, that I want to leverage as an authentication point. My Java application will collect the users username and password (I understand this is deprecated and non-ideal, but for legacy reasons required) and makes a call using the Microsoft adal4j library to an Azure endpoint which I can get to successfully return a JWC access token (in addition to a refresh and ID token).

This is my existing code snippet that retrieves the JWC access token.

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

    if (result == null) {
        System.out.println("ex)");
    }
    return result;
}

public void azureAuthenticate(String authority, String clientID, String username, String password){
    AuthenticationResult result = null;
    try {
        result = getAccessTokenFromUserCredentials(username, password, authority, clientID);
        DecodedJWT accessToken = JWT.decode(result.getAccessToken());
        //Want to verify the validity of this access token
    } catch (Exception ex) {
        ex.printStackTrace();
    }

}

My code is largely based on this Microsoft documentation

After receiving the token, I need to be able to validate its authenticity (I understand the business logic side of confirming its claims, but I am confused as to how to verify the signature is legitimate).

Thank you in advance for any help, I am happy to provide any clarifications needed.


Answer:

The access token from the Azure AD is a JSON Web Token(JWT) which is signed by Security Token Service in private key. A JWT token is a non-encrypted digitally signed JSON payload which contains different attributes (claims) to identify the user. The signature is the last part of the JWT and needs to be used for verification of the payload. This signature was generated with the algorithm described in the header(RS256 if issued from AAD) to prevent unauthorised access.Please refer to this document for more details about JWT token .

To validate signature , firstly we should retrieve and cache the singing tokens (public key) :1)The first call is to the discovery endpoint. It's URL is formed as '/.well-known/openid-configuration' .2) Then you will find lots of metadata here including the issuer value and the jwks_uri endpoint address to get the keys to validate the token's signature .

Token signing is implemented according to JSON Web Key spec. Using Key ID and X.509 certificate thumbprint values from the token's header (kid and x5t parameters respectively) and then find the appropriate public key in the obtained collection of keys to verify the signature. I am not familiar with java ,but you could refer to this thread which includes code sample for how to validate the signature in Java .

Question:

When I get a token by authorization code (authContext.acquireTokenByAuthorizationCode), I get a JWT (idToken) that is signed and has the proper headers:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "wLLmYfsqdQuWtV_-hnVtDJJZM3Q",
  "kid": "wLLmYfsqdQuWtV_-hnVtDJJZM3Q"
}

but when I use the refresh token to get a new token (authContext.acquireTokenByRefreshToken(...)), it returns an unsigned JWT:

{
  "typ": "JWT",
  "alg": "none"
}

How do I get it to give me a signed JWT?

return authContext.acquireTokenByRefreshToken( refreshToken, new ClientCredentials( clientId, clientSecret ), null );


Answer:

I did not reproduce your issue on my side. I followed this tutorial to get Authentication code and acquire access token and refresh token with below code successfully. Please refer to it.

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

import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class GetTokenByAuthenticationCode {

    private static final String APP_ID = "***";
    private static final String APP_SECRET = "***";
    private static final String REDIRECT_URI = "http://localhost:8080";
    private static final String tenant = "***";

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

        String authority = "https://login.microsoftonline.com/" + tenant + "/oauth2/authorize";
        ExecutorService service = Executors.newFixedThreadPool(1);

        String code = "***";

        AuthenticationContext context = new AuthenticationContext(authority, true, service);

        URI url = new URI(REDIRECT_URI);

        Future<AuthenticationResult> result = context.acquireTokenByAuthorizationCode(
                code,
                url,
                new ClientCredential(APP_ID, APP_SECRET),
                null
        );
        String token = result.get().getAccessToken();
        System.out.println(token);
        String refreshToken = result.get().getRefreshToken();
        System.out.println(refreshToken);


        Future<AuthenticationResult> result1 = context.acquireTokenByRefreshToken(
                refreshToken,
                new ClientCredential(APP_ID, APP_SECRET),
                null
        );

        String tokenNew = result1.get().getAccessToken();
        String refreshTokenNew = result1.get().getRefreshToken();
        System.out.println(tokenNew);
        System.out.println(refreshTokenNew);
    }
}

Decode:


Update Answer:

Firstly, sorry for the mistake. I replaced getIdToken with getAccessToken, the result is as same as you.Then I searched the response parameters in Authorize access to Azure Active Directory web applications using the OAuth 2.0 code grant flow, you could find the statement of id_token parameter.

An unsigned JSON Web Token (JWT) representing an ID token. The app can base64Url decode the segments of this token to request information about the user who signed in. The app can cache the values and display them, but it should not rely on them for any authorization or security boundaries.

So, the id token just a segment which can't be relied on. If you want to get the complete id token, please refer to the openId flow.

Question:

I am testing the Microsoft Graph beta endpoint that sends invitations to guest users to join the tenant. The endpoint I am using is :

https://graph.microsoft.com/beta/invitations

Body:

 {
  "invitedUserEmailAddress": "abc@xyz.com",
  "inviteRedirectUrl": "https://myDomain"
 }

I am passing the bearer token in Authorization header that I got for the local admin user through the ADAL4J api. However, this call gives me a 401 Unauthorized error. Following is the response:

{
  "error": {
    "code": "InvalidAuthenticationToken",
    "message": "Access token validation failure.",
    "innerError": {
      "request-id": "91f8129e-70cc-467d-a45b-9309e55788d6",
      "date": "2017-02-10T08:46:09"
    }
  }
}

Any clue on how to get this request working? On Github I have gone through other discussions(eg) where users are facing the same issue.


Answer:

The token sent was obtained with resource as "https://graph.windows.net". The expected resource/audience for Microsoft Graph API is "https://graph.microsoft.com". Update your application manifest to include Microsoft Graph as a resource and request the required permissions. Then request token with above mentioned resource/audience.

Question:

I am using Graph API to import users from Azure AD. Before getting the user list I want to get all the properties available for a user. Is there any API I can use for that. Currently I calling the get all users rest service itself and getting the keys from the first user object. Is there a better way ?


Answer:

You can get all metadata from https://graph.windows.net/"YourTenantId"/$metadata#directoryObjects/Microsoft.DirectoryServices.User

Look for the <EntityType Name="User" ... tag.