I'm trying to get calendars from Office 365 to use them in a REST API (WEB API 2). I already tried a lot of stuff to generate the JWT, but for each try, I get another error.
My application is properly registred in Azure AAD, the public key is uploaded.
The last thing I tried was from this article : https://blogs.msdn.microsoft.com/exchangedev/2015/01/21/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow/
In his example, I can generate the JWT from two differents ways, but I get the error : x-ms-diagnostics: 2000003;reason="The audience claim value is invalid 'https://outlook.office365.com'.";error_category="invalid_resource"
Here is my code :
`
string tenantId = ConfigurationManager.AppSettings.Get("ida:TenantId");
/**
* use the tenant specific endpoint for requesting the app-only access token
*/
string tokenIssueEndpoint = "https://login.windows.net/" + tenantId + "/oauth2/authorize";
string clientId = ConfigurationManager.AppSettings.Get("ida:ClientId");
/**
* sign the assertion with the private key
*/
String certPath = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/cert.pfx");
X509Certificate2 cert = new X509Certificate2(
certPath,
"lol",
X509KeyStorageFlags.MachineKeySet);
/**
* Example building assertion using Json Tokenhandler.
* Sort of cheating, but just if someone wonders ... there are always more ways to do something :-)
*/
Dictionary<string, string> claims = new Dictionary<string, string>()
{
{ "sub", clientId },
{ "jti", Guid.NewGuid().ToString() },
};
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
X509SigningCredentials signingCredentials = new X509SigningCredentials(cert, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest);
JwtSecurityToken selfSignedToken = new JwtSecurityToken(
clientId,
tokenIssueEndpoint,
claims.Select(c => new Claim(c.Key, c.Value)),
DateTime.UtcNow,
DateTime.UtcNow.Add(TimeSpan.FromMinutes(15)),
signingCredentials);
string signedAssertion = tokenHandler.WriteToken(selfSignedToken);
//---- End example with Json Tokenhandler... now to the fun part doing it all ourselves ...
/**
* Example building assertion from scratch with Crypto APIs
*/
JObject clientAssertion = new JObject();
clientAssertion.Add("aud", "https://outlook.office365.com");
clientAssertion.Add("iss", clientId);
clientAssertion.Add("sub", clientId);
clientAssertion.Add("jti", Guid.NewGuid().ToString());
clientAssertion.Add("scp", "Calendars.Read");
clientAssertion.Add("nbf", WebConvert.EpocTime(DateTime.UtcNow + TimeSpan.FromMinutes(-5)));
clientAssertion.Add("exp", WebConvert.EpocTime(DateTime.UtcNow + TimeSpan.FromMinutes(15)));
string assertionPayload = clientAssertion.ToString(Newtonsoft.Json.Formatting.None);
X509AsymmetricSecurityKey x509Key = new X509AsymmetricSecurityKey(cert);
RSACryptoServiceProvider rsa = x509Key.GetAsymmetricAlgorithm(SecurityAlgorithms.RsaSha256Signature, true) as RSACryptoServiceProvider;
RSACryptoServiceProvider newRsa = GetCryptoProviderForSha256(rsa);
SHA256Cng sha = new SHA256Cng();
JObject header = new JObject(new JProperty("alg", "RS256"));
string thumbprint = WebConvert.Base64UrlEncoded(WebConvert.HexStringToBytes(cert.Thumbprint));
header.Add(new JProperty("x5t", thumbprint));
string encodedHeader = WebConvert.Base64UrlEncoded(header.ToString());
string encodedPayload = WebConvert.Base64UrlEncoded(assertionPayload);
string signingInput = String.Concat(encodedHeader, ".", encodedPayload);
byte[] signature = newRsa.SignData(Encoding.UTF8.GetBytes(signingInput), sha);
signedAssertion = string.Format("{0}.{1}.{2}",
encodedHeader,
encodedPayload,
WebConvert.Base64UrlEncoded(signature));
`
My JWT looks like this :
`
{
alg: "RS256",
x5t: "8WkmVEiCU9mHkshRp65lyowGOAk"
}.
{
aud: "https://outlook.office365.com",
iss: "clientId",
sub: "clientId",
jti: "38a34d8a-0764-434f-8e1d-c5774cf37007",
scp: "Calendars.Read",
nbf: 1512977093,
exp: 1512978293
}
`
I put this token in the Authorization header after the "Bearer" string.
Any ideas to solve this kind of issue ? I guess I need a external point of view :)
Thanks