I'm trying to call Microsoft Graph using REST API, and I'm having some problems. My app will eventually be a web app deployed to Azure, and I need to call Graph via REST without a logged-in user.
In trying to debug this, I tried to make the simplest app that I could. This app is just trying to read a user's profile from Azure Active Directory using Graph.
I registered my app in AAD, so I have a tenant, client ID and a client secret. At this point, I've given it every permission under the AAD and Graph APIs (for testing purposes). I'm able to get an token from AAD, but when I call the Graph API with this token, I get 401 - Unauthorized
, with Access Token Validation Error
.
I've searched for this error, and haven't found anything that seems to apply.
EDIT: I've also Granted the permissions to my app after added the permissions.
I've grabbed pieces from various samples in an attempt to get this working. Here's the code:
var tenant = "tenant ID";
var clientID = "app ID";
// I've tried graph.microsoft.com and graph.microsoft.com/.default
var resource = "https://graph.microsoft.com/user.read.all";
var secret = "client secret";
string token;
using(var webClient = new WebClient())
{
var requestParameters = new NameValueCollection();
requestParameters.Add("scope", resource);
requestParameters.Add("client_id", clientID);
requestParameters.Add("grant_type", "client_credentials");
requestParameters.Add("client_secret", secret);
var url = $"https://login.microsoftonline.com/{tenant}/oauth2/token";
var responseBytes = await webClient.UploadValuesTaskAsync(url, "POST", requestParameters);
var responseBody = Encoding.UTF8.GetString(responseBytes);
var jsonObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseBody);
token = jsonObject.Value<string>("access_token");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
var response = await client.GetAsync(new Uri("https://graph.microsoft.com/v1.0/user/<user ID>"));
That second call comes back with the 401 - Unauthorized.
Does anyone see anything that I'm doing wrong, or that I should check?
Thanks!
EDIT: Here's the JSON from the token, decoded with Fiddler with tenant and client IDs removed:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "HHByKU-0DqAqMZh6ZFPd2VWaOtg",
"kid": "HHByKU-0DqAqMZh6ZFPd2VWaOtg"
}
{
"aud": "spn:00000002-0000-0000-c000-000000000000",
"iss": "https://sts.windows.net/<tenant id>/",
"iat": 1507313785,
"nbf": 1507313785,
"exp": 1507317685,
"aio": "Y2VgYCguP8H/lUPs5seMpgeOze3vAA==",
"appid": "~client id~",
"appidacr": "1",
"idp": "https://sts.windows.net/~tenant id~/",
"oid": "37df6326-7ed1-4b88-a57c-b82319a5cb07",
"sub": "37df6326-7ed1-4b88-a57c-b82319a5cb07",
"tenant_region_scope": "NA",
"tid": "~tenant id~",
"uti": "IspHJJNqjUKWjvsWmXhDAA",
"ver": "1.0"
}
requestParameters.Add("scope", resource)
. Should berequestParameters.Add("resource", resource)
andresource
should behttps://graph.microsoft.com
. See details of the authentication procedure here. – Shawn Tabrizi