javamicrosoft-graph-apimsal4j

Refresh Azure AD access token


I am working on a web app where users can login withe their personal Microsoft. After login I store the access token and the refresh token so that I can later retrieve some data from their Microsoft account.

While the access token is valid, everything works.

final TokenCredential tokenCredential = request -> {
    final OffsetDateTime offset = OffsetDateTime.ofInstant(account.getTokenExpiry().toInstant(), ZoneId.systemDefault());
    final AccessToken token = new AccessToken(account.getAccessToken(), offset);
    return Mono.create(sink -> sink.success(token));
};

final TokenCredentialAuthProvider tokenCredentialAuthProvider = 
  new TokenCredentialAuthProvider(tokenCredential);

this.graphServiceClient =
    GraphServiceClient
        .builder()
        .authenticationProvider(tokenCredentialAuthProvider)
        .buildClient();

The problem is that if the token has expired, I can't just provide the refresh token. I need to first retrieve the new token. Is there a way of doing this? Is there a method where I can just provide both tokens and the refresh is handled automatically?

I could not find anything useful so far.


Solution

  • I could not find the exact API in the libraries, I did manage to solve it using normal REST calls:

    private String getAccessToken(String refreshToken) throws UnsupportedOperationException {
        String url = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
    
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    
        // TODO: These values need to be read from the config file
        MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
        map.add("client_id", "your_client_id");
        map.add("grant_type", "refresh_token");
        map.add("redirect_uri", "http://localhost:5000/login/oauth2/code/microsoft");
        map.add("scope", "your scopes");
        map.add("refresh_token", refreshToken);
        map.add("client_secret", "your_client_secret");
    
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
    
        ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
        return response.getBody();
    }