Skip to content

Instantly share code, notes, and snippets.

@PawelHaracz
Created June 5, 2019 09:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PawelHaracz/9c04ae3517ca739c378dce94eb400c98 to your computer and use it in GitHub Desktop.
Save PawelHaracz/9c04ae3517ca739c378dce94eb400c98 to your computer and use it in GitHub Desktop.
the validator checks whitelist and decodes token and compare this with appId claim;
public class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None,
TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
var cultureUi = CultureInfo.CurrentUICulture;
var culture = CultureInfo.CurrentCulture;
return _myTaskFactory.StartNew(() =>
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = cultureUi;
return func();
}).Unwrap().GetAwaiter().GetResult();
}
public static void RunSync(Func<Task> func)
{
var cultureUi = CultureInfo.CurrentUICulture;
var culture = CultureInfo.CurrentCulture;
_myTaskFactory.StartNew(() =>
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = cultureUi;
return func();
}).Unwrap().GetAwaiter().GetResult();
}
}
public class WhitelistAppTokenValidation : ISecurityTokenValidator
{
private readonly string _tenatId;
private readonly string _authority;
private readonly Guid[] _whitelist;
public WhitelistAppTokenValidation(string authority, string tenatId, params Guid[] whiteList)
{
_tenatId = string.IsNullOrWhiteSpace(tenatId) == false ? tenatId : throw new ArgumentException(nameof(tenatId));
_authority = string.IsNullOrWhiteSpace(authority) == false ? authority : throw new ArgumentException(nameof(authority));
_whitelist = whiteList != null && whiteList.Any() ? whiteList : throw new ArgumentException(nameof(ArgumentException));
}
public bool CanReadToken(string securityToken) => true;
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
string stsDiscoveryEndpoint = $"{_authority}/{_tenatId}/v2.0/.well-known/openid-configuration";
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
var config = AsyncHelper.RunSync(configManager.GetConfigurationAsync);
validationParameters.IssuerSigningKeys = config.SigningKeys;
var validationIssuerOldValue = validationParameters.ValidateIssuer;
var validateAudiencedOldValue = validationParameters.ValidateAudience;
validationParameters.ValidateIssuer = false;
validationParameters.ValidateAudience = false;
var tokenHandler = new JwtSecurityTokenHandler();
var result = tokenHandler.ValidateToken(securityToken, validationParameters, out validatedToken);
var claimValue = result.Claims.GetEnumerator();
var appId = Guid.Empty;
if (claimValue != null)
{
while (claimValue.MoveNext())
{
if (claimValue.Current.Type == "appid")
{
var aId = claimValue.Current.Value;
if (Guid.TryParse(aId, out appId) == false)
{
throw new InvalidCastException($"Cannot cast string {aId} to guid");
}
break;
}
}
}
if (appId == Guid.Empty)
{
throw new UnauthorizedException($"Token doesn't have application Id");
}
if (_whitelist.Contains(appId) == false)
{
throw new UnauthorizedException($"An application Id {appId} isn't being in whitelist");
}
validationParameters.ValidateIssuer = validationIssuerOldValue;
validationParameters.ValidateAudience = validateAudiencedOldValue;
return result;
}
public bool CanValidateToken { get; } = true;
public int MaximumTokenSizeInBytes { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment