Проблемы при отправке электронной почты с графиком ms с использованием clientsecret и azure AD tennant, работает в тесте, но не QA и Production. (Разные tennants) - PullRequest
0 голосов
/ 23 марта 2020

Проблемы с отправкой электронной почты в средах qa и prod. Тестирование и разработка работают.

Ошибка:

Код: generalException Сообщение: при отправке запроса произошла ошибка. В этом процессе аутентификации используется неправильное приложение (publi c или конфиденциальное). Потенциальная проблема: URI перенаправления действителен, но он был настроен для неправильного типа приложения. Проверьте конфигурацию приложения, используемого на портале регистрации приложений. Подробнее см. https://aka.ms/msal-net-invalid-client. Исходное исключение: AADSTS7000215: указан неверный секретный ключ клиента. Идентификатор трассировки: dd40b2e6-4ede-4f94-9d08-14533d138d00 Идентификатор корреляции: 3ca08d24-5634-4c99-93ba-4df9a45292bd Метка времени: 2020-03-02 06: 49: 12Z

Получите следующий HTTP-статус по запросу sendt. 200 https://.vault.azure.net: 443 / secrets / MailClientSecret /? Api-version = 7.0 200 https://login.microsoftonline.com: 443 / common / discovery / instance? Api-version = 1.1 & authorization_endpoint = https% 3A% 2F% 2Flogin.microsoftonline. com% 2F % 2Fauth2% 2Fv2.0% 2 Разрешить

200 https://login.microsoftonline.com: 443 / / v2.0 / .well-known / openid-configuration

401 (не утвержден) https://login.microsoftonline.com: 443 / / oauth2 / v2.0 / токен

 public async Task SendMail(string[] tooAdress, string subject, string body, FileAttachment[] fileAttachments)
    {

        if (tooAdress.Length > 0) 
        {

            string overRideEmail = Configuration.GetValue<string>("Email:OverrideRecipientNotProductionEmail");
            if (Environment.EnvironmentName != Environments.Production || overRideEmail.Length > 0)
            {
                var email = new List<string>();                    
                email.Add(overRideEmail);
                tooAdress = email.ToArray();
                subject = Environment.EnvironmentName + " - " + subject;
            }


            // The app registration should be configured to require access to permissions
            // sufficient for the Microsoft Graph API calls the app will be making, and
            // those permissions should be granted by a tenant administrator.
            var scopes = new string[] { "https://graph.microsoft.com/.default" };

            // Configure the MSAL client as a confidential client
            var clientId = Configuration.GetValue<string>("AzureAD:ClientId");
            var tennantId = Configuration.GetValue<string>("AzureAD:TenantId");
            var senderObjectId = Configuration.GetValue<string>("Email:MailBoxSenderObjectId"); 

            var clientSecret = LoadClientSecretFromKeyVault(Configuration).Result;

            string secret = Uri.EscapeUriString(clientSecret.Value);

            var confidentialClient = ConfidentialClientApplicationBuilder
                .Create(clientId)
                .WithAuthority($"https://login.microsoftonline.com/"+ tennantId + "/v2.0")
                .WithClientSecret(secret)
                .Build();

            // Build the Microsoft Graph client. As the authentication provider, set an async lambda
            // which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
            // and inserts this access token in the Authorization header of each API request. 
            GraphServiceClient graphServiceClient =
                new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => {

                    // Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
                    var authResult = await confidentialClient
                        .AcquireTokenForClient(scopes)
                        .ExecuteAsync();

                    // Add the access token in the Authorization header of the API request.
                    requestMessage.Headers.Authorization =
                        new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
                    })
                );

            //Make attachment
            MessageAttachmentsCollectionPage attachments = new MessageAttachmentsCollectionPage();
            foreach (FileAttachment fileStream in fileAttachments) {
                attachments.Add(fileStream);
            }

            //Make recipients
            List<Recipient> toRecipients = new List<Recipient>();
            foreach (string emailAdress in tooAdress) {
                toRecipients.Add(new Recipient
                {
                    EmailAddress = new EmailAddress
                    {
                        Address = emailAdress.Trim()
                    }
                });
            }


            // Make a Microsoft Graph API query
            var message = new Message
            {
                Subject = subject,
                Body = new ItemBody
                {
                    ContentType = BodyType.Text,
                    Content = body
                },
                ToRecipients = toRecipients,
                Attachments = attachments
            };

            var saveToSentItems = true;

            await graphServiceClient.Users[senderObjectId]
                .SendMail(message, saveToSentItems)
                .Request()
                .PostAsync();
        }
    }


    /// <summary>
    /// Loads the client secret from a KeyVault in Azure.
    /// </summary>
    /// <example>
    /// var conStr = LoadConnectionStringFromKeyVault(getConfig(), getServices()).Result.Value;
    /// </example>
    /// <param name="config">Environment config</param>
    /// <returns>The connection string</returns>
    private async Task<SecretBundle> LoadClientSecretFromKeyVault(IConfiguration config)
    {
        AzureServiceTokenProvider tokenProvider = new AzureServiceTokenProvider();
        KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback));

        var vaultUrl = $"https://{config.GetValue<string>("KeyVault:VaultName")}.vault.azure.net/secrets/{config.GetValue<string>("KeyVault:MailClientSecretKeyName")}";
        return await keyVaultClient.GetSecretAsync(vaultUrl).ConfigureAwait(false);
    }

}
...