无法通过Azure通信服务并使用登录用户的凭据从本地计算机发送电子邮件

ktca8awb  于 2023-05-18  发布在  其他
关注(0)|答案(3)|浏览(406)

我正在尝试使用Azure通信服务和DefaultAzureCredential从本地计算机发送电子邮件,但收到以下错误:

Azure.Identity.AuthenticationFailedException: Azure CLI authentication failed due to an unknown error. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/azclicredential/troubleshoot 
ERROR: AADSTS65002: Consent between first party application '04b07795-8ddb-461a-bbee-02f9e1bf7b46' 
and first party resource '632ec9eb-fad7-4cbd-993a-e72973ba2acc' must be configured via preauthorization - applications owned and operated by Microsoft must get approval from the API owner before requesting tokens for that API.

下面是失败的代码:

using Azure;
using Azure.Communication.Email;
using Azure.Identity;

var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions() { TenantId = "my-tenant-id" });
client = new EmailClient(new Uri("https://mydomain.communication.azure.com/"), credentials);
var subject = "Welcome to Azure Communication Service Email APIs.";
var htmlContent = "<html><body><h1>Quick send email test</h1><br/><h4>This email message is sent from Azure Communication Service Email.</h4><p>This mail was sent using .NET SDK!!</p></body></html>";
var sender = "DoNotReply@mydomain.com";
var recipient = "user@mydomain.com";

var message = new EmailMessage(sender, recipient, new EmailContent(subject) { Html = htmlContent });
var operation = await client.SendAsync(WaitUntil.Started, message);

如果我使用服务主体,同样的代码也可以工作。下面是正在工作的代码:

using Azure;
using Azure.Communication.Email;
using Azure.Identity;

var credentials = new ClientSecretCredential("tenant-id",
    "client-id", "client-secret");;
client = new EmailClient(new Uri("https://mydomain.communication.azure.com/"), credentials);
var subject = "Welcome to Azure Communication Service Email APIs.";
var htmlContent = "<html><body><h1>Quick send email test</h1><br/><h4>This email message is sent from Azure Communication Service Email.</h4><p>This mail was sent using .NET SDK!!</p></body></html>";
var sender = "DoNotReply@mydomain.com";
var recipient = "user@mydomain.com";

var message = new EmailMessage(sender, recipient, new EmailContent(subject) { Html = htmlContent });
var operation = await client.SendAsync(WaitUntil.Started, message);

接受的答案提供Azure Communication Services - How do I authenticate against Azure IAM建议我使用服务主体,并且工作正常,但是我不想使用服务主体
同一问题中提供的其他答案提到用户应该是Contributor角色,而登录用户确实具有该角色。

是否有一种方法可以使用登录用户的凭据而不是服务主体从本地计算机发送电子邮件?

um6iljoc

um6iljoc1#

转换为答案:
目前,建议将服务原则信息存储在环境变量中,而不是代码中。Use Azure Active Directory in Communication Services。我能够重现这个问题,它最有可能是由我们的资源提供商不支持这种情况的限制引起的。我已经将反馈传达给我们的ACS产品工程团队,一旦我们有更多更新,我会在这里分享。

k10s72fa

k10s72fa2#

我能够使用下面的代码发送电子邮件使用我的登录凭据。我确认我没有任何环境变量可以给出错误的结果。最初,在后端配置中有一个问题,但已得到解决。

using Azure;
using Azure.Communication.Email;
using Azure.Identity;

namespace SendEmail
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            // This code demonstrates how to authenticate to your Communication Service resource using
            string resourceEndpoint = "https://<redacted>.communication.azure.com";
            EmailClient emailClient = new EmailClient(new Uri(resourceEndpoint), new DefaultAzureCredential());

            //Replace with your domain and modify the content, recipient details as required

            var subject = "Welcome to Azure Communication Service Email APIs.";
            var htmlContent = "<html><body><h1>Quick send email test</h1><br/><h4>This email message is sent from Azure Communication Service Email.</h4><p>This mail was sent using .NET SDK!!</p></body></html>";
            var sender = "DoNotReply@<redacted>.azurecomm.net";
            var recipient = "<redacted>@microsoft.com";

            try
            {
                Console.WriteLine("Sending email...");
                EmailSendOperation emailSendOperation = await emailClient.SendAsync(
                    Azure.WaitUntil.Completed,
                    sender,
                    recipient,
                    subject,
                    htmlContent);
                EmailSendResult statusMonitor = emailSendOperation.Value;

                Console.WriteLine($"Email Sent. Status = {emailSendOperation.Value.Status}");

                /// Get the OperationId so that it can be used for tracking the message for troubleshooting
                string operationId = emailSendOperation.Id;
                Console.WriteLine($"Email operation id = {operationId}");
            }
            catch (RequestFailedException ex)
            {
                /// OperationID is contained in the exception message and can be used for troubleshooting purposes
                Console.WriteLine($"Email send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}");
            }
        }
    }
}

我从Windows PowerShell使用az登录来登录。
下面是当我使用具有访问资源权限的登录名时的输出:Console output of a successful email send request
下面是我使用登录名但不访问资源时的输出:Console output of an unsuccessful email send request
从命令行中使用以下命令确认您能够接收访问令牌。在更新之前,这不起作用。

az account get-access-token --resource https://communication.azure.com

我会再次检查这篇文章,以防有另一个相关的问题导致你的问题。

iovurdzv

iovurdzv3#

我在使用我的用户登录帐户或服务主体发送ACS电子邮件(或使用任何其他Azure服务)时没有遇到任何问题。错误消息可能意味着您必须首先使用Azure命令行界面(CLI)登录,登录将是经过同意的交互登录。

使用DefaultAzureCredential类

DefaultAzureCredential类应该足以满足您的所有需求。
参考:https://learn.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential
我在你的代码中看到了2个案例,DefaultAzureCredential可以用于你的2个案例。并且不应该在源代码中放入任何敏感信息。

1.如果您想使用您登录的用户:

var credential = new DefaultAzureCredential();
// or new DefaultAzureCredential(includeInteractiveCredentials: false);

您必须首先使用您的用户登录,运行az login并完成交互登录,然后再运行.NET应用程序。
https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli
如果您有多个Azure订阅,则可能需要先切换到订阅(要测试发送电子邮件的Azure资源的订阅)

az account show  # check the current active subscription

az account list  # list all subscriptions

az account set --subscription "3b558d3a-.........-465701d89f9d"

2.如果要使用服务主体

var credential = new DefaultAzureCredential();
// or new DefaultAzureCredential(includeInteractiveCredentials: false);
// same C# code as case using your user logged in

在开发人员计算机上设置环境:可以在Windows环境变量设置上设置AZURE_TENANT_ID、AZURE_CLIENT_ID和AZURE_CLIENT_SECRET

您还可以在Visual Studio上的launchSettings.json中将Azure凭据设置为Environment(dotnet run也使用launchSettings.json)

记住不要将这个带有服务主体凭据的launchSettings.json提交到git仓库

3.在Azure上,您还可以使用DefaultAzureCredential进行托管身份,这比服务主体安全得多。

  • 如果在Azure上为应用程序使用系统分配的托管标识,则不要提供任何AZURE_CLIENT_ID
  • 如果使用用户分配的托管身份,请确保设置用户分配的托管身份的AZURE_CLIENT_ID

使用ACS电子邮件的Azure凭据,而不是ACS电子邮件AzureKeyCredential或连接字符串

  • 在代码中,将DefaultAzureCredential用作(1)。对于已登录的用户,请确保首先运行az login,或运行az account show以查看您是否已登录。
  • 将您的用户帐户(或服务主体或托管身份)授予ACS(访问控制(IAM))上的角色Contributor

然后就足够在ACS电子邮件上发送电子邮件了。

相关问题