private void VerifyComputedLifetime(DateTime created, DateTime expires) { var now = SystemClock.UtcNow.UtcDateTime; // if expires in past, throw if (DateTimeUtil.Add(DateTimeUtil.ToUniversalTime(expires), Options.MaxClockSkew) < now) { throw new InvalidRequestException("ID2075", created, expires, now); } // if creation time specified is greater than one day in future, throw if (DateTimeUtil.ToUniversalTime(created) > DateTimeUtil.Add(now + TimeSpan.FromDays(1), Options.MaxClockSkew)) { throw new InvalidRequestException("ID2076", created, expires, now); } // if expiration time is equal to or before creation time, throw. This would be hard to make happen as the Lifetime class checks this condition in the constructor if (expires <= created) { throw new InvalidRequestException("ID2077", created, expires); } // if timespan is greater than allowed, throw if ((expires - created) > Options.MaxTokenLifetime) { throw new InvalidRequestException("ID2078", created, expires, Options.MaxTokenLifetime); } }
public override System.IdentityModel.Tokens.SecurityToken CreateToken(Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) { Utility.VerifyNonNullArgument("tokenDescriptor", tokenDescriptor); if (tokenDescriptor.SigningCredentials == null) { throw new System.ArgumentException("tokenDescriptor.SigningCredentials cannot be null"); } if (tokenDescriptor.Subject == null) { throw new System.ArgumentException("tokenDescriptor.Subject cannot be null"); } if (string.IsNullOrEmpty(tokenDescriptor.TokenIssuerName)) { throw new System.ArgumentException("tokenDescriptor.TokenIssuerName cannot be null"); } System.DateTime dateTime = System.DateTime.UtcNow; System.DateTime validTo = DateTimeUtil.Add(dateTime, System.TimeSpan.FromHours(1.0)); if (tokenDescriptor.Lifetime != null) { if (tokenDescriptor.Lifetime.Created.HasValue) { dateTime = DateTimeUtil.ToUniversalTime(tokenDescriptor.Lifetime.Created.Value); } if (tokenDescriptor.Lifetime.Expires.HasValue) { validTo = DateTimeUtil.ToUniversalTime(tokenDescriptor.Lifetime.Expires.Value); } } System.Collections.Generic.List <JsonWebTokenClaim> list = new System.Collections.Generic.List <JsonWebTokenClaim>(); foreach (Claim current in tokenDescriptor.Subject.Claims) { list.Add(new JsonWebTokenClaim(current.ClaimType, current.Value)); } return(new JsonWebSecurityToken(tokenDescriptor.TokenIssuerName, this.GetAppliesTo(tokenDescriptor), dateTime, validTo, list, tokenDescriptor.SigningCredentials)); }
/// <summary> /// Validates the lifetime of a <see cref="SecurityToken"/>. /// </summary> /// <param name="notBefore">The 'notBefore' time found in the <see cref="SecurityToken"/>.</param> /// <param name="expires">The 'expiration' time found in the <see cref="SecurityToken"/>.</param> /// <param name="securityToken">The <see cref="SecurityToken"/> being validated.</param> /// <param name="validationParameters"><see cref="TokenValidationParameters"/> required for validation.</param> /// <exception cref="ArgumentNullException"> if 'vaidationParameters' is null.</exception> /// <exception cref="SecurityTokenNoExpirationException"> if 'expires.HasValue' is false and <see cref="TokenValidationParameters.RequireExpirationTime"/> is true.</exception> /// <exception cref="SecurityTokenInvalidLifetimeException"> if 'notBefore' is > 'expires'.</exception> /// <exception cref="SecurityTokenNotYetValidException"> if 'notBefore' is > DateTime.UtcNow.</exception> /// <exception cref="SecurityTokenExpiredException"> if 'expires' is < DateTime.UtcNow.</exception> /// <remarks>All time comparisons apply <see cref="TokenValidationParameters.ClockSkew"/>.</remarks> public static void ValidateLifetime(DateTime?notBefore, DateTime?expires, SecurityToken securityToken, TokenValidationParameters validationParameters) { if (validationParameters == null) { throw new ArgumentNullException("validationParameters"); } if (!validationParameters.ValidateLifetime) { return; } if (!expires.HasValue && validationParameters.RequireExpirationTime) { throw new SecurityTokenNoExpirationException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10225, securityToken == null ? "null" : securityToken.GetType().ToString())); } if (notBefore.HasValue && expires.HasValue && (notBefore.Value > expires.Value)) { throw new SecurityTokenInvalidLifetimeException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10224, notBefore.Value, expires.Value)); } DateTime utcNow = DateTime.UtcNow; if (notBefore.HasValue && (notBefore.Value > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew))) { throw new SecurityTokenNotYetValidException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10222, notBefore.Value, utcNow)); } if (expires.HasValue && (expires.Value < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))) { throw new SecurityTokenExpiredException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10223, expires.Value, utcNow)); } }
public static System.DateTime AddNonNegative(System.DateTime time, System.TimeSpan timeSpan) { if (timeSpan < System.TimeSpan.Zero) { throw new System.ArgumentException("TimeSpan must be greater than or equal to TimeSpan.Zero.", "timeSpan"); } return(DateTimeUtil.Add(time, timeSpan)); }
/// <summary> /// Requests that then next call to <see cref="GetConfigurationAsync()"/> obtain new configuration. /// <para>If the last refresh was greater than <see cref="RefreshInterval"/> then the next call to <see cref="GetConfigurationAsync()"/> will retrieve new configuration.</para> /// <para>If <see cref="RefreshInterval"/> == <see cref="TimeSpan.MaxValue"/> then this method does nothing.</para> /// </summary> public void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; if (now >= DateTimeUtil.Add(_lastRefresh.UtcDateTime, RefreshInterval)) { _syncAfter = now; } }
/// <summary> /// Creates a DateTime from epoch time. /// </summary> /// <param name="secondsSinceUnixEpoch">Number of seconds.</param> /// <returns>The DateTime in UTC.</returns> public static DateTime DateTime(long secondsSinceUnixEpoch) { if (secondsSinceUnixEpoch <= 0) { return(UnixEpoch); } return(DateTimeUtil.Add(UnixEpoch, TimeSpan.FromSeconds(secondsSinceUnixEpoch)).ToUniversalTime()); }
/// <summary> /// Obtains an updated version of Configuration. /// </summary> /// <param name="cancel">CancellationToken</param> /// <returns>Configuration of type T.</returns> /// <remarks>If the time since the last call is less than <see cref="AutomaticRefreshInterval"/> then <see cref="IConfigurationRetriever{T}.GetConfigurationAsync"/> is not called and the current Configuration is returned.</remarks> public async Task <T> GetConfigurationAsync(CancellationToken cancel) { DateTimeOffset now = DateTimeOffset.UtcNow; if (_currentConfiguration != null && _syncAfter > now) { return(_currentConfiguration); } await _refreshLock.WaitAsync(cancel).ConfigureAwait(false); try { if (_syncAfter <= now) { try { // Don't use the individual CT here, this is a shared operation that shouldn't be affected by an individual's cancellation. // The transport should have it's own timeouts, etc.. _currentConfiguration = await _configRetriever.GetConfigurationAsync(_metadataAddress, _docRetriever, CancellationToken.None).ConfigureAwait(false); Contract.Assert(_currentConfiguration != null); _lastRefresh = now; _syncAfter = DateTimeUtil.Add(now.UtcDateTime, _automaticRefreshInterval); } catch (Exception ex) { _syncAfter = DateTimeUtil.Add(now.UtcDateTime, _automaticRefreshInterval < _refreshInterval ? _automaticRefreshInterval : _refreshInterval); if (_currentConfiguration == null) // Throw an exception if there's no configuration to return. { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX20803, (_metadataAddress ?? "null")), ex)); } else { LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX20806, (_metadataAddress ?? "null")), ex)); } } } // Stale metadata is better than no metadata if (_currentConfiguration != null) { return(_currentConfiguration); } else { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX20803, (_metadataAddress ?? "null")))); } } finally { _refreshLock.Release(); } }
/// <summary> /// Requests that then next call to <see cref="GetConfigurationAsync()"/> obtain new configuration. /// <para>If it is a first force refresh or the last refresh was greater than <see cref="BaseConfigurationManager.RefreshInterval"/> then the next call to <see cref="GetConfigurationAsync()"/> will retrieve new configuration.</para> /// <para>If <see cref="BaseConfigurationManager.RefreshInterval"/> == <see cref="TimeSpan.MaxValue"/> then this method does nothing.</para> /// </summary> public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; if (_isFirstRefreshRequest) { _syncAfter = now; _isFirstRefreshRequest = false; } else if (now >= DateTimeUtil.Add(_lastRefresh.UtcDateTime, RefreshInterval)) { _syncAfter = now; } }
public void AddContext(SecurityContextSecurityToken token) { // // WCF will cache the token first before calling the WrappedSessionSecurityTokenHandler.OnTokenIssued. // We need to map the claims here so we will be caching the correct token with Geneva Claims substitued // in place of the WCF claims. // _claimsHandler.SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy(token); SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, token.ContextId, token.KeyGeneration); SessionSecurityToken sessionToken = SecurityContextSecurityTokenHelper.ConvertSctToSessionToken(token, SecureConversationVersion.Default); DateTime expiryTime = DateTimeUtil.Add(sessionToken.ValidTo, _claimsHandler.SecurityTokenHandlerCollection.Configuration.MaxClockSkew); _tokenCache.AddOrUpdate(key, sessionToken, expiryTime); }
/// <summary> /// Obtains an updated version of Configuration. /// </summary> /// <param name="cancel">CancellationToken</param> /// <returns>Configuration of type T.</returns> /// <remarks>If the time since the last call is less than <see cref="AutomaticRefreshInterval"/> then <see cref="IConfigurationRetriever{T}.GetConfigurationAsync"/> is not called and the current Configuration is returned.</remarks> public async Task <T> GetConfigurationAsync(CancellationToken cancel) { DateTimeOffset now = DateTimeOffset.UtcNow; if (_currentConfiguration != null && _syncAfter > now) { return(_currentConfiguration); } await _refreshLock.WaitAsync(cancel); try { Exception retrieveEx = null; if (_syncAfter <= now) { try { // Don't use the individual CT here, this is a shared operation that shouldn't be affected by an individual's cancellation. // The transport should have it's own timeouts, etc.. _currentConfiguration = await _configRetriever.GetConfigurationAsync(_metadataAddress, _docRetriever, CancellationToken.None); Contract.Assert(_currentConfiguration != null); _lastRefresh = now; _syncAfter = DateTimeUtil.Add(now.UtcDateTime, _automaticRefreshInterval); } catch (Exception ex) { retrieveEx = ex; _syncAfter = DateTimeUtil.Add(now.UtcDateTime, _automaticRefreshInterval < _refreshInterval ? _automaticRefreshInterval : _refreshInterval); } } if (_currentConfiguration == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10803, _metadataAddress ?? "null"), retrieveEx); } // Stale metadata is better than no metadata return(_currentConfiguration); } finally { _refreshLock.Release(); } }
public void UpdateContextCachingTime(SecurityContextSecurityToken token, DateTime expirationTime) { if (token.ValidTo <= expirationTime.ToUniversalTime()) { return; } SessionSecurityTokenCacheKey key = new SessionSecurityTokenCacheKey(_claimsHandler.EndpointId, token.ContextId, token.KeyGeneration); SessionSecurityToken sessionToken = SecurityContextSecurityTokenHelper.ConvertSctToSessionToken(token, SecureConversationVersion.Default); DateTime expiryTime = DateTimeUtil.Add(sessionToken.ValidTo, _claimsHandler.SecurityTokenHandlerCollection.Configuration.MaxClockSkew); if (_tokenCache.Get(key) == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4285, sessionToken.ContextId.ToString())); } _tokenCache.AddOrUpdate(key, sessionToken, expiryTime); }