Exemple #1
0
        public async Task Invoke(HttpContext context)
        {
            if (!_hasProvider)
            {
                await _next.Invoke(context);

                return;
            }

            try
            {
                // Add Telemetry.
                using (var activity = _activitySource?.StartActivity("Create Arc4u Principal", ActivityKind.Producer))
                {
                    var clientSecret = GetClientSecretIfExist(context, _option.SecretKey);

                    bool basicAuthenticationSecret = !String.IsNullOrWhiteSpace(clientSecret);

                    bool certificateAuthenticationSecret = false;
                    // Check for a secret key encrypted.
                    if (_hasCertificate && !basicAuthenticationSecret)
                    {
                        clientSecret = GetClientSecretIfExist(context, _option.Certificate.SecretKey);
                        certificateAuthenticationSecret = !String.IsNullOrWhiteSpace(clientSecret);
                    }

                    if (!String.IsNullOrWhiteSpace(clientSecret))
                    {
                        CredentialsResult credential = null;

                        if (basicAuthenticationSecret)
                        {
                            credential = GetCredential(clientSecret);
                        }

                        if (certificateAuthenticationSecret)
                        {
                            credential = GetCertificateCredential(clientSecret);
                        }

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

                            // 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);
        }
        public async Task <TokenInfo> GetTokenAsync(IKeyValueSettings settings, CredentialsResult credential)
        {
            var messages = GetContext(settings, out string clientId, out string authority, 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();

            // no cache, do a direct call on every calls.
            Logger.Technical().From <CredentialTokenProvider>().System($"Call STS: {authority} for user: {credential.Upn}").Log();
            return(await GetTokenInfoAsync(serviceApplicationId, clientId, authority, credential.Upn, credential.Password));
        }
        protected async Task <TokenInfo> CreateBasicTokenInfoAsync(IKeyValueSettings settings, CredentialsResult credential)
        {
            var basicTokenProvider = Container.Resolve <ICredentialTokenProvider>(CredentialTokenProvider.ProviderName);

            return(await basicTokenProvider.GetTokenAsync(settings, credential));
        }
        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));
        }
 private static string BuildKey(CredentialsResult credential, string authority, string serviceApplicationId)
 {
     return(authority + "_" + serviceApplicationId + "_Password_" + credential.Upn + "_" + credential.Password.GetHashCode().ToString());
 }