// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNet.Security.Cookies;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Identity.Authentication
{
///
/// Static helper class used to configure a CookieAuthenticationProvider to validate a cookie against a user's security
/// stamp
///
public static class SecurityStampValidator
{
///
/// Can be used as the ValidateIdentity method for a CookieAuthenticationProvider which will check a user's security
/// stamp after validateInterval
/// Rejects the identity if the stamp changes, and otherwise will call regenerateIdentity to sign in a new
/// ClaimsIdentity
///
///
///
///
///
public static Func OnValidateIdentity(
TimeSpan validateInterval)
where TUser : class
{
return OnValidateIdentity(validateInterval, id => id.GetUserId());
}
///
/// Can be used as the ValidateIdentity method for a CookieAuthenticationProvider which will check a user's security
/// stamp after validateInterval
/// Rejects the identity if the stamp changes, and otherwise will call regenerateIdentity to sign in a new
/// ClaimsIdentity
///
///
///
///
///
///
///
public static Func OnValidateIdentity(
TimeSpan validateInterval,
Func getUserIdCallback)
where TUser : class
{
return async context =>
{
var currentUtc = DateTimeOffset.UtcNow;
if (context.Options != null && context.Options.SystemClock != null)
{
currentUtc = context.Options.SystemClock.UtcNow;
}
var issuedUtc = context.Properties.IssuedUtc;
// Only validate if enough time has elapsed
var validate = (issuedUtc == null);
if (issuedUtc != null)
{
var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
validate = timeElapsed > validateInterval;
}
if (validate)
{
var manager = context.HttpContext.RequestServices.GetService>();
var userId = getUserIdCallback(context.Identity);
var user = await manager.ValidateSecurityStampAsync(context.Identity, userId);
if (user != null)
{
bool isPersistent = false;
if (context.Properties != null)
{
isPersistent = context.Properties.IsPersistent;
}
await manager.SignInAsync(user, isPersistent);
}
else
{
context.RejectIdentity();
manager.SignOut();
}
}
};
}
}
}