I am building a console application
in C#.
I want to make some calls to Microsoft Graph API to access and edit some Excel files in my SharePoint so I can automate some processes in my Organization.
The logic of the app is simple.
Azure Active Directory
to authenticate this console application using the clients credential flow which means we will provide a clientsID and AppKey. I took the clientsID and AppKey from Azure Active Directory > App Registrations.
https://graph.microsoft.com/v1.0/me/
{
"error": {
"code": "InvalidAuthenticationToken",
"message": "Access token validation failure. Invalid audience.",
"innerError": {
"request-id": "0a3ec**************",
"date": "2019-10-15T13:54:33"
}
}
}
Below you will find the full code of my application with the two methods of getting the access token and calling the Graph API:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IdentityModel.Tokens;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using AuthenticationContext = Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext;
namespace Project_Budget
{
class Program
{
private const string clientId = "14f1****************";
private const string aadInstance = "https://login.microsoftonline.com/{0}";
private const string tenant = "******.onmicrosoft.com";
private const string resource = "https://graph.windows.net";
private const string appKey = "IKV***********";
static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
private static HttpClient httpClient = new HttpClient();
private static AuthenticationContext context = null;
private static ClientCredential credential = null;
static void Main(string[] args)
{
context = new AuthenticationContext(authority);
credential = new ClientCredential(clientId,appKey);
Task<string> token = GetToken();
token.Wait();
//Console.WriteLine(token.Result + "\n");
Task<string> graphCall = GetExcelFile(token.Result);
graphCall.Wait();
Console.WriteLine(graphCall.Result + "\n");
Console.ReadLine();
}
private static async Task<string> GetExcelFile(string result)
{
string apiJsonResult = null;
var apiCallString = "https://graph.microsoft.com/v1.0/me/";
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result);
var getResult = await httpClient.GetAsync(apiCallString);
if (getResult.Content != null)
{
apiJsonResult = await getResult.Content.ReadAsStringAsync();
}
return apiJsonResult;
}
private static async Task<string> GetToken()
{
AuthenticationResult result = null;
string token = null;
result = await context.AcquireTokenAsync(resource, credential); //authentication context object
token = result.AccessToken;
return token;
}
}
}
I have given all the access required for the app to run. Also I run the query on Graph Explorer
and runs properly.
Why do I get this error on the console application?
Ideally, the resource should actually be
private const string resource = "https://graph.microsoft.com";
But you still need to select the scopes that you want to target in your application. The way you are doing it at the moment does seem to acquire/set the relevant scopes which is done for you by Graph Explorer.
I would suggest following this quick start tutorial on how to build a dot net core console app and you should be up and running in no time. It uses the MSAL library which works better than the ADAL library you are using in your scenario.
https://docs.microsoft.com/en-us/graph/tutorials/dotnet-core
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With