Search code examples
javaoffice365adalmicrosoft-graph-apiazure-ad-graph-api

403:forbidden when reading mails from server side application using Microsoft Graph


I'm developing a server side application to retrieve emails from our Office 365, filter the emails and store it in our DB without users login. Here is a link to my previous question if you want to see some details.

I've the following methods

@Test
    public void testGetAccessTokenDeamon() throws Exception {

        String tenant="f0245-fd24-r3s-be8a-7745gra60be3";
        String authority = "https://login.windows.net/"+tenant+"/oauth2/authorize";
        ExecutorService service=null;
        service= Executors.newFixedThreadPool(1);

        try{

            AuthenticationContext authenticationContext= new AuthenticationContext(authority,false,service);
            String certFile="/mycert.pfx";
            InputStream pkcs12Cert= new SharedFileInputStream(certFile);

            AsymmetricKeyCredential credential=AsymmetricKeyCredential.create("g564f4-e53c-45b7-938a-gt6445gy667",pkcs12Cert,"passwd");


            Future<AuthenticationResult> future=authenticationContext.acquireToken("https://graph.microsoft.com",credential,null);

            System.out.println("Token Received"+future.get().getAccessToken());
            String token = future.get().getAccessToken();

            HttpGet httpGet = new HttpGet("https://graph.microsoft.com/v1.0/users");

            httpGet.setHeader("Authorization", "Bearer "+token);


            GraphServices graphServices = new GraphServices();
            ResponseEntity<String> responseEntity;


            responseEntity = graphServices.getEmails(token);




            //HttpClient httpClient= HttpClients.createDefault();

            //HttpResponse response=httpClient.execute(httpGet);
            //HttpEntity entity=response.getEntity();

        }
        catch (MalformedURLException e){
            e.printStackTrace();

        }
        catch (Exception e){
            e.printStackTrace();
        }


    }

public ResponseEntity<String> getEmails(String accessToken) throws Exception
    {
        logger.info("In getEmails");

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> request;

        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add(AuthorizationConstants.AUTHORIZATION, AuthorizationConstants.BEARER + " " + accessToken);
        request = new HttpEntity<String>(headers);

        ResponseEntity<String> response = restTemplate.exchange("https://graph.microsoft.com/v1.0/users/[email protected]/messages", HttpMethod.GET, request, String.class);
        return response;
    }

If I try to use https://graph.microsoft.com/v1.0/users/ in the restTemplate I will get a list of users but for a specific user the above code returns 403.

Can you please advice me which end points to use so that my app can access individual messages without users login ? I've already gave the app all permissions (delegate and app permissions) that are necessary.

UPDATE: This is what I have when I run the token on http://jwt.calebb.net/ and couldn't find the scp/scope section.

{
 typ: "JWT",
 alg: "RS256",
 x5t: "xxxxx_mfg5JKHrwLBbd_4s",
 kid: "xxxxx_mfg5JKHrwLBbd_4s"
}.
{
 aud: "https://graph.microsoft.com",
 iss: "https://sts.windows.net/f456fyu44-df44-d3t3-f342-66423er4323/",
 iat: 1473280446,
 nbf: 1473280446,
 exp: 1473284346,
 appid: "4fw423gh-er423-45b7-zd32-3fwer2343szd",
 appidacr: "2",
 e_exp: 10800,
 idp: "https://sts.windows.net/g0412253-aeb2-4a8a-ju76-8736272a3u7e3/",
 oid: "33dd3455-0195-4708-rt44-34552321ds32d2",
 sub: "33dd3455-0195-4708-813d-34552321ds32d2",
 tid: "33dd3455-ae23-r456-be8a-7737cf4321d2e3",
 ver: "1.0"
}.
[signature]

Here are the permissions I gave (all permissions for now) for the app.

Microsoft Graph - Application Permissions: 18 -Delegated Permissions: 40 Windows Azure Active Directory -Application Permissions: 4 - Delegated Permissions: 8 Office 365 Exchange Online -Application Permissions: 9- Delegated Permissions: 30


Solution

  • I've already gave the app all permissions (delegate and app permissions) that are necessary.

    This is probably not the case :). Typically 403 forbidden means your token doesn't have the required scope (in the scp claim) for the API you're calling. Easy way to find out: grab the token in the debugger (it's a big long base64 string), then head over to http://jwt.calebb.net/ and paste it in. You'll see it decoded into a JSON web token. Look for the roles claim:

    roles: [
      "Calendars.Read",
      "Mail.Read",
      "Contacts.Read" 
    ],
    

    If you don't have Mail.Read or Mail.ReadWrite, you don't have the necessary permissions configured.