1
votes

I'm trying to request an access token and a refresh token from Microsoft Graph, but adding "offline_access" to the scope makes the scope invalid.

This is for a service where a user gives us access to an Outlook Calendar once and after that the service checks their calendar every 20 minutes for events. I have managed to get consent and pull data when requesting access to "User.Read" and "Calendars.Read", but when I add "offline_access" I get the message The provided resource value for the input parameter 'scope' is not valid.

I have an array with the permissions I want

private static final String[] ACCESS_PERMISSIONS = {
            "https://graph.microsoft.com/User.Read",
            "https://graph.microsoft.com/Calendars.Read",
            "https://graph.microsoft.com/offline_access",
    };

and then combine and encode them

String encodedScope = URLEncoder.encode(
Arrays.stream(ACCESS_PERMISSIONS)
.reduce(
(a,b) -> a + " " + b)
.get(), "UTF-8").replace("+","%20");

which results in the string https%3A%2F%2Fgraph.microsoft.com%2FUser.Read%20https%3A%2F%2Fgraph.microsoft.com%2FCalendars.Read%20https%3A%2F%2Fgraph.microsoft.com%2Foffline_access Then I request the tokens

String appId = "client_id=" + clientID;
String scope = "&scope=" + encodedScope;
String authCode = "&code=" + code;
String redirect = "&redirect_uri=" + redirectUri;
String grantType = "&grant_type=authorization_code";
String secret = "&client_secret=" + clientSecret;

String data = appId + scope + authCode + redirect + grantType + secret;

// Create POST request
URL url = new URL(postUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

// Configure request
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);

// Send data
OutputStream os = connection.getOutputStream();
byte[] inputBytes = data.getBytes(ENCODING);
os.write(inputBytes, 0, inputBytes.length); // Bytes, Offset, Length

The final link then looks like

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=[CLIENT ID]
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fsport%2Fauth%2Foutlook
&response_mode=query
&scope=https%3A%2F%2Fgraph.microsoft.com%2FUser.Read%20https%3A%2F%2Fgraph.microsoft.com%2FCalendars.Read%20https%3A%2F%2Fgraph.microsoft.com%2Foffline_access
&state=2737

I would expect this to return an access token and a refresh token, but as previously mentioned I get the message that the resource value for the scope is not valid.

It is essential for the service to be able to refresh the tokens as it should run about a year without intervention.

1

1 Answers

4
votes

The scope isn't https://graph.microsoft.com/offline_access, it is simply offline_access. Offline Access is a special AAD scope that tells it to return a Refresh Token, it isn't a Microsoft Graph scope.

You can actually drop https://graph.microsoft.com/ across the board. The only time you need to specify the FQDN is when you're requesting the default set of scopes from the app registration (i.e. https://graph.microsoft.com/.default) but that is generally only used when you're using App-Only/Daemon authentication flow (Client Credentials).