public async Task Invoke(HttpContext context)
        {
            if (!_hasProvider)
            {
                await _next(context);

                return;
            }

            try
            {
                TokenInfo tokenInfo;

                if (context.Request.Headers.ContainsKey("Authorization"))
                {
                    if (context.Request.Headers.TryGetValue("Authorization", out var authzValue) && authzValue.Any(value => value.Contains("Basic")))
                    {
                        // Add Telemetry.
                        using (var activity = _activitySource?.StartActivity("BasicAuthentication", ActivityKind.Producer))
                        {
                            var cacheKey = BuildKey(authzValue);

                            tokenInfo = _tokenCache?.Get <TokenInfo>(cacheKey);
                            if (null == tokenInfo || tokenInfo.ExpiresOnUtc < DateTime.UtcNow.AddMinutes(1))
                            {
                                var credential = GetCredential(authzValue);

                                if (null != credential && credential.CredentialsEntered)
                                {
                                    // Get an Access Token.
                                    tokenInfo = await _provider.GetTokenAsync(_option.Settings, credential);

                                    _tokenCache?.Put(cacheKey, tokenInfo);
                                }
                            }

                            if (null != tokenInfo)
                            {
                                // Replace the Basic Authorization by the access token in the header.
                                var authorization = new AuthenticationHeaderValue("Bearer", tokenInfo.AccessToken).ToString();
                                context.Request.Headers.Remove("Authorization");
                                context.Request.Headers.Add("Authorization", authorization);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Technical().Exception(ex).Log();
            }

            await _next(context);
        }
Example #2
0
        private void AfterAccessNotification(TokenCacheNotificationArgs args)
        {
            if (HasStateChanged)
            {
                Logger.Technical().From <Cache>().System($"Adding token information to the cache for the identifier: {_identifier}.").Log();
                TokenCache.Put(_identifier, SerializeAdalV3());
                Logger.Technical().From <Cache>().System($"Added token information to the cache for the identifier: {_identifier}.").Log();

                HasStateChanged = false;
            }
        }
        public async Task <TokenInfo> GetTokenAsync(IKeyValueSettings settings, CredentialsResult credential)
        {
            var messages = GetContext(settings, out string clientId, out string authority, out string authenticationType, out string serviceApplicationId);

            if (String.IsNullOrWhiteSpace(credential.Upn))
            {
                messages.Add(new Message(ServiceModel.MessageCategory.Technical, ServiceModel.MessageType.Warning, "No Username is provided."));
            }

            if (String.IsNullOrWhiteSpace(credential.Password))
            {
                messages.Add(new Message(ServiceModel.MessageCategory.Technical, ServiceModel.MessageType.Warning, "No password is provided."));
            }

            messages.LogAndThrowIfNecessary(this);
            messages.Clear();

            if (null != TokenCache)
            {
                // Get a HashCode from the password so a second call with the same upn but with a wrong password will not be impersonated due to
                // the lack of password check.
                var cacheKey = BuildKey(credential, authority, serviceApplicationId);
                Logger.Technical().From <CredentialTokenCacheTokenProvider>().System($"Check if the cache contains a token for {cacheKey}.").Log();
                var tokenInfo  = TokenCache.Get <TokenInfo>(cacheKey);
                var hasChanged = false;

                if (null != tokenInfo)
                {
                    Logger.Technical().From <CredentialTokenCacheTokenProvider>().System($"Token loaded from the cache for {cacheKey}.").Log();

                    if (tokenInfo.ExpiresOnUtc < DateTime.UtcNow.AddMinutes(1))
                    {
                        Logger.Technical().From <CredentialTokenCacheTokenProvider>().System($"Token is expired for {cacheKey}.").Log();

                        // We need to refresh the token.
                        tokenInfo = await CreateBasicTokenInfoAsync(settings, credential);

                        hasChanged = true;
                    }
                }
                else
                {
                    Logger.Technical().From <CredentialTokenCacheTokenProvider>().System($"Contact the STS to create an access token for {cacheKey}.").Log();
                    tokenInfo = await CreateBasicTokenInfoAsync(settings, credential);

                    hasChanged = true;
                }

                if (hasChanged)
                {
                    try
                    {
                        Logger.Technical().From <CredentialTokenCacheTokenProvider>().System($"Save the token in the cache for {cacheKey}, will expire at {tokenInfo.ExpiresOnUtc} Utc.").Log();
                        TokenCache.Put(cacheKey, tokenInfo);
                    }
                    catch (Exception ex)
                    {
                        Logger.Technical().From <CredentialTokenCacheTokenProvider>().Exception(ex).Log();
                    }
                }

                return(tokenInfo);
            }

            // no cache, do a direct call on every calls.
            Logger.Technical().From <CredentialTokenCacheTokenProvider>().System($"No cache is defined. STS is called for every call.").Log();
            return(await CreateBasicTokenInfoAsync(settings, credential));
        }