Skip to content

Instantly share code, notes, and snippets.

@watahani
Last active April 26, 2023 08:03
Show Gist options
  • Save watahani/6ddd7f1cbd8197c30e4adad9d09a6c12 to your computer and use it in GitHub Desktop.
Save watahani/6ddd7f1cbd8197c30e4adad9d09a6c12 to your computer and use it in GitHub Desktop.
This code validates the Microsoft Graph API tokens, but it is just experimental code. You SHOUD NOT validate tokens issued by other APIs than the one you control, not just the Microsoft Graph API. If you are trying to implement a program based on this code,chill out and read carefully the following thread. https://github.com/AzureAD/azure-active…
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Protocols;
using System.Text;
using System.Text.RegularExpressions;
// This code validates the Microsoft Graph API tokens, but it is just experimental code.
// You SHOUD NOT validate tokens issued by other APIs than the one you control, not just the Microsoft Graph API.
// If you are trying to implement a program based on this code,chill out and read carefully the following thread.
// https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609
byte[] DecodeBase64Url(string header)
{
//replace '-' with '+' and '_' with '/'
header = header.Replace('-', '+').Replace('_', '/');
//check if it is valid base64 string
switch (header.Length % 4)
{
case 0:
break;
case 2:
header += "==";
break;
case 3:
header += "=";
break;
default:
throw new System.Exception("Invalid base64url string");
}
return System.Convert.FromBase64String(header);
}
string EncodeBase64Url(byte[] input)
{
//replace '+' with '-' and '/' with '_'
var s = System.Convert.ToBase64String(input).Replace('+', '-').Replace('/', '_');
//remove last = padding
return s.Replace("=", "");
}
//enable pii logging
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
Console.Write("Enter the Graph token:");
var token = Console.ReadLine();
var header = token.Split('.')[0];
var headerJson = Encoding.UTF8.GetString(DecodeBase64Url(header));
string pattern = "\"nonce\":\"(.+?)\"";
var nonce = Regex.Match(headerJson, pattern).Groups[1].Value;
byte[] hash;
//get sha256 hash of nonce
using(var sha256 = System.Security.Cryptography.SHA256.Create())
{
hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(nonce));
}
var newNonce = EncodeBase64Url(hash);
//replace nonce with newNonce
var newHeaderJson = Regex.Replace(headerJson, pattern, $"\"nonce\":\"{newNonce}\"");
//replace header
var newHeader = EncodeBase64Url(Encoding.UTF8.GetBytes(newHeaderJson));
var newToken = token.Replace(header, newHeader);
Console.WriteLine(newToken);
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
var parameters = new TokenValidationParameters()
{
ConfigurationManager = configManager,
ValidAudience = "00000003-0000-0000-c000-000000000000",
ValidateIssuer = false
};
var handler = new JsonWebTokenHandler();
try
{
var result = handler.ValidateToken(newToken, parameters);
Console.WriteLine(result.IsValid);
Console.WriteLine(result.Exception);
foreach (var claim in result.Claims)
{
System.Console.WriteLine($"{claim.Key}: {claim.Value}");
}
}
catch (SecurityTokenException e)
{
System.Console.WriteLine(e.Message);
throw;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment