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);
            }
        }
Пример #2
0
 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));
 }
Пример #3
0
        /// <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 &gt; 'expires'.</exception>
        /// <exception cref="SecurityTokenNotYetValidException"> if 'notBefore' is &gt; DateTime.UtcNow.</exception>
        /// <exception cref="SecurityTokenExpiredException"> if 'expires' is &lt; 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));
            }
        }
Пример #4
0
 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));
 }
Пример #5
0
        /// <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;
            }
        }
Пример #6
0
        /// <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());
        }
Пример #7
0
        /// <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;
            }
        }
Пример #9
0
        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();
            }
        }
Пример #11
0
        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);
        }