-
-
Save infamousjoeg/7d94337b898763231aa16f1044681806 to your computer and use it in GitHub Desktop.
Validating an ADFS JWT token
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace ValidateJWTConsoleApp | |
{ | |
class Helper | |
{ | |
internal static class AsyncHelper | |
{ | |
private static readonly TaskFactory TaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); | |
public static void RunSync(Func<Task> func) | |
{ | |
TaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult(); | |
} | |
public static TResult RunSync<TResult>(Func<Task<TResult>> func) | |
{ | |
return TaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IdentityModel.Tokens.Jwt; | |
using System.Threading; | |
using Microsoft.IdentityModel.Protocols; | |
using Microsoft.IdentityModel.Protocols.OpenIdConnect; | |
using Microsoft.IdentityModel.Tokens; | |
using static ValidateJWTConsoleApp.Helper; | |
// Derived from https://www.jerriepelser.com/blog/manually-validating-rs256-jwt-dotnet/ | |
namespace ValidateJWTConsoleApp | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// ADFS FQDN | |
const string ADFSDomain = "https://my-adfs/adfs/"; | |
// Identifier | |
const string ADFSAudience = "https://localhost:44326/"; | |
const string testToken = "eyJ...6-1A"; | |
try | |
{ | |
// Download the OIDC configuration which contains the JWKS | |
// NB!!: Downloading this takes time, so do not do it very time you need to validate a token, Try and do it only once in the lifetime of your application!! | |
IConfigurationManager<OpenIdConnectConfiguration> configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{ADFSDomain}.well-known/openid-configuration", | |
new OpenIdConnectConfigurationRetriever()); | |
OpenIdConnectConfiguration openIdConfig = AsyncHelper.RunSync(async () => await configurationManager.GetConfigurationAsync(CancellationToken.None)); | |
// Configure the TokenValidationParameters. Assign the SigningKeys which were downloaded from ADFS. | |
// Also set the Issuer and Audience(s) to validate. | |
// Note: You need to set the ADFS domain as above so that the program can find the /adfs/.well-known/openid-configuration endpoint. | |
// However, this is not the issuer in the token so you need to add the /adfs/services/trust endpoint as below. | |
// If this is not configured corrrectly, you get the exception: | |
// Message=IDX10205: Issuer validation failed. Issuer: 'http://my-adfs/adfs/services/trust'. | |
// Did not match: validationParameters.ValidIssuer: 'https://my-adfs/adfs/' or validationParameters.ValidIssuers: 'null'. | |
TokenValidationParameters validationParameters = | |
new TokenValidationParameters | |
{ | |
ValidIssuer = ADFSDomain, | |
ValidIssuers = new[] { ADFSDomain, "http://my-adfs/adfs/services/trust" }, | |
ValidAudiences = new[] { ADFSAudience }, | |
IssuerSigningKeys = openIdConfig.SigningKeys | |
}; | |
// Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method | |
SecurityToken validatedToken; | |
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); | |
var user = handler.ValidateToken(testToken, validationParameters, out validatedToken); | |
// The ValidateToken method above will return a ClaimsPrincipal. Get the claims form user.Claims. | |
// These are OAuth claims e.g. "aud", "iss" etc. | |
Console.WriteLine("Token is validated" + "\n"); | |
foreach (var Claim in user.Claims) | |
{ | |
Console.WriteLine("Claim is " + Claim); | |
} | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine($"Error occurred while validating token: {e.Message}"); | |
} | |
Console.WriteLine(); | |
Console.WriteLine("Press ENTER to continue..."); | |
Console.ReadLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment