protected async Task <string> PostAuthenticate(HttpResponseMessage response)
        {
            // An HTTP 401 Not Authorized error; handle if an authentication callback has been supplied
            if (OnAuthenticate != null)
            {
                // Extract the WWW-Authenticate header and determine if it represents an OAuth2 Bearer challenge
                var authenticateHeader = response.Headers.WwwAuthenticate.ElementAt(0).ToString();

                if (HttpBearerChallenge.IsBearerChallenge(authenticateHeader))
                {
                    var challenge = new HttpBearerChallenge(response.RequestMessage.RequestUri, authenticateHeader);

                    if (challenge != null)
                    {
                        // Update challenge cache
                        HttpBearerChallengeCache.GetInstance().SetChallengeForURL(response.RequestMessage.RequestUri, challenge);

                        // We have an authentication challenge, use it to get a new authorization token
                        return(await OnAuthenticate(challenge.AuthorizationServer, challenge.Resource, challenge.Scope).ConfigureAwait(false));
                    }
                }
            }

            return(null);
        }
        protected async Task<string> PostAuthenticate(HttpResponseMessage response)
        {
            // An HTTP 401 Not Authorized error; handle if an authentication callback has been supplied
            if (OnAuthenticate != null)
            {
                // Extract the WWW-Authenticate header and determine if it represents an OAuth2 Bearer challenge
                var authenticateHeader = response.Headers.WwwAuthenticate.ElementAt(0).ToString();

                if (HttpBearerChallenge.IsBearerChallenge(authenticateHeader))
                {
                    var challenge = new HttpBearerChallenge(response.RequestMessage.RequestUri, authenticateHeader);

                    if (challenge != null)
                    {
                        // Update challenge cache
                        HttpBearerChallengeCache.GetInstance().SetChallengeForURL(response.RequestMessage.RequestUri, challenge);

                        // We have an authentication challenge, use it to get a new authorization token
                        return await OnAuthenticate(challenge.AuthorizationServer, challenge.Resource, challenge.Scope).ConfigureAwait(false);
                    }
                }
            }

            return null;
        }
        /// <summary>
        /// Gets the challenge for the cached URL.
        /// </summary>
        /// <param name="url"> the URL that the challenge is cached for.</param>
        /// <returns>the cached challenge or null otherwise.</returns>
        public HttpBearerChallenge GetChallengeForURL(Uri url)
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            HttpBearerChallenge value = null;

            lock (_cacheLock)
            {
                _cache.TryGetValue(url.FullAuthority(), out value);
            }

            return(value);
        }
        public HttpBearerChallenge this[Uri url]
        {
            get
            {
                if (url == null)
                {
                    throw new ArgumentNullException("url");
                }

                HttpBearerChallenge value = null;

                lock ( _cacheLock )
                {
                    _cache.TryGetValue(url.FullAuthority(), out value);
                }

                return(value);
            }
            set
            {
                if (url == null)
                {
                    throw new ArgumentNullException("url");
                }

                if (value != null && string.Compare(url.FullAuthority(), value.SourceAuthority, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    throw new ArgumentException("Source URL and Challenge URL do not match");
                }

                lock ( _cacheLock )
                {
                    if (value == null)
                    {
                        _cache.Remove(url.FullAuthority());
                    }
                    else
                    {
                        _cache[url.FullAuthority()] = value;
                    }
                }
            }
        }
        /// <summary>
        /// Caches the challenge for the specified URL
        /// </summary>
        /// <param name="url"> URL corresponding to challenge as cache key </param>
        /// <param name="value"> the challenge </param>
        public void SetChallengeForURL(Uri url, HttpBearerChallenge value)
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (string.Compare(url.FullAuthority(), value.SourceAuthority, StringComparison.OrdinalIgnoreCase) != 0)
            {
                throw new ArgumentException("Source URL and Challenge URL do not match");
            }

            lock (_cacheLock)
            {
                _cache[url.FullAuthority()] = value;
            }
        }
        public void SetChallengeForURL(Uri url, HttpBearerChallenge value)
        {
            if (url == null)
                throw new ArgumentNullException("url");

            if (value == null)
                throw new ArgumentNullException("value");

            if (string.Compare(url.FullAuthority(), value.SourceAuthority, StringComparison.OrdinalIgnoreCase) != 0)
                throw new ArgumentException("Source URL and Challenge URL do not match");

            lock (_cacheLock)
            {
                _cache[url.FullAuthority()] = value;
            }
        }