0

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

Tech_sharma
  • 117
  • 2
  • 11
  • I think you can't get both Graph based scope and non-Graph one (EWS). Try getting just the EWS one id you're planning to use EWS: "https://outlook.office.com/EWS.AccessAsUser.All" Or get the Graph scopes and then user Graph API – Alexey Aug 28 '21 at 16:03

1 Answers1

2

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://learn.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

DmitryArc
  • 4,757
  • 2
  • 37
  • 42
Glen Scales
  • 20,495
  • 1
  • 20
  • 23
  • Thank you so much @GlenScales for you response. I have change the resource and api permission as you suggested, now I am getting another error **The request failed. ExchangeImpersonation SOAP header must be present for this type of OAuth token** Can you guide me here how can I add soap header in the request – Tech_sharma Aug 05 '21 at 06:51