Authentication & Authorization
Custom lifetime validation
Workaround for: AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/92
There is currently an issue with the default lifetime validation for a token, where if the token expires after 19/01/2038 12:00:00 AM it overflows the int value causing the DateTime recieved by the default LifetimeValidatier to be null.
The following is a custom LifetimeValidator method that can be used in TokenValidationParameters. It resolves the issue by wrapping the default LifetimeValidator provided in Microsoft.IdentityModel.Tokens and using the ValidTo property on the Security Token passed to the method if the criteria is met.
public bool CustomLifetimeValidator(
DateTime? notBefore,
DateTime? expires,
SecurityToken securityToken,
TokenValidationParameters validationParameters)
{
if (!expires.HasValue && validationParameters.RequireExpirationTime)
{
var overflowDate = DateTimeOffset.FromUnixTimeSeconds(int.MaxValue).DateTime;
if (securityToken is not null && securityToken.ValidTo >= overflowDate)
expires = securityToken.ValidTo;
}
// Prevents validation loop
var newParameters = validationParameters.Clone();
newParameters.LifetimeValidator = null;
// Use the default validation logic with the new expiry time
Validators.ValidateLifetime(notBefore, expires, securityToken, newParameters);
return true;
}
TenantId Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class TenantIdAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private readonly string[] _ids;
public TenantIdAttribute(params string[] validIds)
{
_ids = validIds;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = context.HttpContext.User;
if (!user.Identity.IsAuthenticated)
{
context.Result = new ForbidResult();
return;
}
foreach(var claim in _ids)
{
if(user.HasClaim("TenantId", claim.ToString()))
return;
}
context.Result = new ForbidResult();
}
}
[TenantId("c34c8a15-a93f-41c9-9325-35f20811651e")]
[Authorize]
[HttpGet]
[Route("results")]
public IActionResult GetResults()
{
...
return Ok();
}