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()); }