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();
}