Search code examples
asp.netoauth-2.0microsoft-graph-apioffice365api

invalid_scope error AADSTS70011, Why I am getting this error


public string[] scopes1 = new string[]
{
    "https://graph.microsoft.com/User.Read",
    "https://graph.microsoft.com/User.ReadWrite",
    "https://graph.microsoft.com/User.ReadBasic.All",
    "https://graph.microsoft.com/Mail.Send",
    "https://graph.microsoft.com/Calendars.ReadWrite",
    "https://graph.microsoft.com/Mail.ReadWrite",
    "https://graph.microsoft.com/Files.ReadWrite",

};

public async Task<string> GetAccessToken2()
{
    string url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?";//https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(url);


        // We want the response to be JSON.
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        // Build up the data to POST.
        List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
        postData.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
        postData.Add(new KeyValuePair<string, string>("client_id", appId));
        postData.Add(new KeyValuePair<string, string>("client_secret", appPassword));
        postData.Add(new KeyValuePair<string, string>("response_type", "code"));
        postData.Add(new KeyValuePair<string, string>("response_mode", "query"));
        // postData.Add(new KeyValuePair<string, string>("client_secret", appPassword));               
        //postData.Add(new KeyValuePair<string, string>("client_secret", appPassword));
        postData.Add(new KeyValuePair<string, string>("redirect_uri", "http://localhost/5341/Home/AddC"));
        postData.Add(new KeyValuePair<string, string>("Scope",string.Join(" ", scopes1)));// "openid offline_access https://graph.microsoft.com/mail.read"));
        postData.Add(new KeyValuePair<string, string>("state", "12345"));

        FormUrlEncodedContent content = new FormUrlEncodedContent(postData);

        // Post to the Server and parse the response.
        HttpResponseMessage response = await client.PostAsync("Token", content);
        string jsonString = await response.Content.ReadAsStringAsync();
        object responseData = JsonConvert.DeserializeObject(jsonString);             

        // return the Access Token.
        return ((dynamic)responseData).access_token;
    }
}

{"error":"invalid_scope","error_description":"AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://graph.microsoft.com/User.Read https://graph.microsoft.com/User.ReadWrite https://graph.microsoft.com/User.ReadBasic.All https://graph.microsoft.com/Mail.Send https://graph.microsoft.com/Calendars.ReadWrite https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Files.ReadWrite is not valid.\r\nTrace ID: 17e465ac-9aca-4615-8021-f48ee8f00900\r\nCorrelation ID: 47a584ed-07ca-4a51-bdd1-8cb7364de3ee\r\nTimestamp: 2017-09-15 12:39:26Z","error_codes":[70011],"timestamp":"2017-09-15 12:39:26Z","trace_id":"17e465ac-9aca-4615-8021-f48ee8f00900","correlation_id":"47a584ed-07ca-4a51-bdd1-8cb7364de3ee"}


Solution

  • The call to https://login.microsoftonline.com/common/oauth2/v2.0/authorize is an HTTP GET, not a POST. It is the callback function that takes the authorization code and issues a POST to https://login.microsoftonline.com/common/oauth2/v2.0/token.

    The prototype for the initial GET is (new lines for readability):

    https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
    client_id=[APPLICATION ID]&
    response_type=code&
    redirect_uri=[REDIRECT URI]&
    scope=[SCOPE]
    

    The second stage issues a POST. That prototype is:

    POST URL: https://login.microsoftonline.com/common/oauth2/v2.0/token
    POST HEADER: Content-Type: application/x-www-form-urlencoded
    POST BODY: grant_type=authorization_code&code=[AUTHORIZATION CODE]&
               client_id=[APPLICATION ID]&client_secret=[PASSWORD]
               &scope=[SCOPE]&redirect_uri=[REDIRECT URI]
    

    Also not that this isn't JSON, the Content-Type is application/x-www-form-urlencoded.

    I wrote an article a while back that walks through the Authorization Code Flow with the v2 Endpoint, you might find it helpful: Microsoft v2 Endpoint Primer