0
votes

I am trying to do modern authentication for outlook mailbox(which is used to send mail from applications) using microsoft graph access token. I am succssfully getting the access token from the below code:

   public class AuthTokenAccess {

public AuthTokenAccess() {}

public static String getAccessToken(String tenantId, String clientId, String clientSecret, String scope)
         {
    String endpoint = String.format("https://login.microsoftonline.com/%s/oauth2/token", tenantId);
    String postBody = String.format("grant_type=client_credentials&client_id=%s&client_secret=%s&resource=%s&scope=%s",
            clientId, clientSecret, "https://management.azure.com/", scope);
    String accessToken = null;
    try{
        HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
    
    
        conn.setRequestMethod("POST");
    
    conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    conn.setDoOutput(true);
    conn.getOutputStream().write(postBody.getBytes());
    conn.connect();
    JsonFactory factory = new JsonFactory();
    JsonParser parser = factory.createParser(conn.getInputStream());
    //String accessToken = null;
    while (parser.nextToken() != JsonToken.END_OBJECT) {
        String name = parser.getCurrentName();
        if ("access_token".equals(name)) {
            parser.nextToken();
            accessToken = parser.getText();
        }
    }
    }catch(Exception e) {
        
        
    }
    return accessToken;
}

after getting the access token I am sending this to ExchangeService:

  public ExchangeService getExchangeServiceObj(String emailId, String token, String emailServerURI) throws URISyntaxException {

    ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
        
        if(service != null) {
            service.getHttpHeaders().put("Authorization", "Bearer " + token);
            service.getHttpHeaders().put("X-AnchorMailbox", emailId);
            service.setUrl(new URI(emailServerURI));   //https://outlook.office365.com/EWS/Exchange.asmx
        }
    
    LOGGER.debug("getExchangeServiceObj() {}.", "ends");
    return service;
}

Here, I am getting the ExchangeService object but when I am trying send mail microsoft.exchange.webservices.data.core.service.item.EmailMessage.sendAndSaveCopy() throws Exception

  public void sendMail(String toMail, String ccMail, String subject, String body, String pathOfFileToAttach) {

        ExchangeService emailService = getExchangeServiceObj(
                ResourceUtils.getPropertyValue("email_user"), 
                token, 
                ResourceUtils.getPropertyValue("ews_server"));

        if(!StringUtils.hasText(toMail)) { 
            toMail = ccMail;
        }
        EmailMessage emessage = new EmailMessage(emailService);
        
        emessage.setSubject(subject);
        String strBodyMessage = body;
        strBodyMessage = strBodyMessage + "<br /><br />";
        LOGGER.info("Body: {} ", body);
        MessageBody msg = new MessageBody(BodyType.HTML, strBodyMessage);
        emessage.setBody(msg);
        
        emessage.sendAndSaveCopy();
        LOGGER.info("Email send {}", "sucessfully");
    } catch(Exception e) {
        LOGGER.error(Constants.ERROR_STACK_TRACE, e);
        throw new CommonException(e);
    }
}

Tried with below scopes: "https://outlook.office.com/EWS.AccessAsUser.All", "https://graph.microsoft.com/.default"

Below is the access token I am getting using the above code:

{"aud": "https://management.azure.com/", "iss": "https://sts.windows.net/3863b7d0-213d-40f3-a4d0-6cd90452245a/", "iat": 1628068305, "nbf": 1628068305, "exp": 1628072205, "aio": "E2ZgYEjcvsaipUV1wxwxrne/9F4XAAA=", "appid": "055eb578-4716-4901-861b-92f2469dac9c", "appidacr": "1", "idp": "https://sts.windows.net/3863b7d0-213d-40f3-a4d0-6cd90452245a/", "oid": "33688cee-e16e-4d11-8ae0-a804805ea007", "rh": "0.AUYA0LdjOD0h80Ck0GzZBFIkWni1XgUWRwFJhhuS8kadrJxGAAA.", "sub": "33688cee-e16e-4d11-8ae0-a804805ea007", "tid": "3863b7d0-213d-40f3-a4d0-6cd90452245a", "uti": "nZUVod_e3EuO_T-Ter-_AQ", "ver": "1.0", "xms_tcdt": 1626687774 }

as you could see scope is not included in the token. Do I need to pass any other thing while getting the token.

Azure active directory set up:

  1. registered application 2.Create client secret 3.Added redirect URL enter image description here

  2. added permission enter image description here

Can someone please help me here, where I am doing mistake or is other any other way to make it work. Thank you

1

1 Answers

0
votes

I can see a few issue here first your using the client credentials flow which requires that you assign Application Permission and you only have Delegate permission, with EWS the only Application permission that will work is full_access_as_app see https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth (app-only section)

        String endpoint = String.format("https://login.microsoftonline.com/%s/oauth2/token", tenantId);
String postBody = String.format("grant_type=client_credentials&client_id=%s&client_secret=%s&resource=%s&scope=%s",
        clientId, clientSecret, "https://management.azure.com/", scope);

Your mixing V1 and V2 authentication (see https://nicolgit.github.io/AzureAD-Endopoint-V1-vs-V2-comparison/) here which won't work (scope will just be ignored) for the v1 endpoint eg what you have in https://login.microsoftonline.com/%s/oauth2/token is the V1 auth endpoint so your request shouldn't include the scope just the resource and that resource should be https://outlook.office.com