0

I'm using Azure Communication Services for SMS and emails. It works just fine if I use it with an endpoint and an access key or with the connection string itself. However, that's not a good practice and I would like to authenticate against Azure IAM.

Speaking of it, what role should I assign in the following context?

  1. In the Azure portal, navigate to the Azure Communication Services resource that you want to use for sending SMS messages.
  2. Click on the "Access control (IAM)" tab in the left-hand menu.
  3. Click on the "Add role assignment" button
  4. Do what?

Here is a link to the documentation https://learn.microsoft.com/en-us/azure/communication-services/concepts/authentication#azure-ad-authentication

I switched to the following overload:

var options = new DefaultAzureCredentialOptions
{
    ExcludeInteractiveBrowserCredential = false,
    ExcludeManagedIdentityCredential = true,
    ExcludeSharedTokenCacheCredential = false,
    InteractiveBrowserTenantId = tenantId,
    InteractiveBrowserCredentialClientId = clientId,
    ManagedIdentityClientId = clientId,
    SharedTokenCacheTenantId = tenantId,
    TenantId = tenantId,
    VisualStudioTenantId = tenantId,
    VisualStudioCodeTenantId = tenantId
};
var tokenCredentials = new DefaultAzureCredential(options);

var emailClient = new EmailClient(new Uri(uri), tokenCredentials);

This is the error message that I get after I try to send SMS or an email.

enter image description here

and when I try to do: az login --scope https://communication.azure.com//.default, it fails with the following message:

enter image description here

Please note that this is happening only for Azure Communication Services. There are other services such as Key Vault, AppConfiguration, etc. that work just fine with IAM.

Code that works but uses Access Key instead of IAM

public sealed class AzureEmailNotificationService
{
    private readonly EmailConfiguration _emailConfiguration;
    private readonly EmailClient _emailClient;

    public AzureEmailNotificationService(IOptions<EmailConfiguration> options)
    {
        ArgumentNullException.ThrowIfNull(options.Value);
        
        _emailConfiguration = options.Value;
        _emailClient = new EmailClient(new Uri(_emailConfiguration.Endpoint), new AzureKeyCredential(_emailConfiguration.AccessKey));
    }

    public async Task SendAsync(string subject, string message, string recipient, CancellationToken cancellationToken = default)
    {
        var emailContent = new EmailContent(subject) { PlainText = message };
        var emailAddresses = new List<EmailAddress> { new(recipient) };
        var emailRecipients = new EmailRecipients(emailAddresses);
        
        await _emailClient.SendAsync(new EmailMessage(_emailConfiguration.From, emailContent, emailRecipients), cancellationToken);
    }
}

public sealed class AzureSmsNotificationService
{
    private readonly SmsConfiguration _smsConfiguration;
    private readonly SmsClient _smsClient;

    public AzureSmsNotificationService(IOptions<SmsConfiguration> options)
    {
        ArgumentNullException.ThrowIfNull(options.Value);
        
        _smsConfiguration = options.Value;
        _smsClient = new SmsClient(new Uri(_smsConfiguration.Endpoint), new AzureKeyCredential(_smsConfiguration.AccessKey));   
    }

    public async Task SendAsync(string message, string recipient, CancellationToken cancellationToken = default)
    {
        await _smsClient.SendAsync(_smsConfiguration.From, recipient, message, cancellationToken: cancellationToken);
    }
}
nop
  • 4,711
  • 6
  • 32
  • 93

3 Answers3

3

I tried to reproduce the same in my environment and got below results:

When I ran below CLI command same as you, I got same error like this:

az login --scope https://communication.azure.com//.default

Response:

enter image description here

It opened browser where I got same error again after signing in like this:

enter image description here

To resolve the error, try running only az login command at first to sign in to your Azure account like this:

enter image description here

As for the role assignment, check how you created the service principal.

If you run below CLI command, it will create service principal by assigning it Contributor role under subscription with response like this:

az ad sp create-for-rbac --name <application-name> --role Contributor --scopes /subscriptions/<subscription-id>

Response:

enter image description here

Now set environment variables with above values in response as mentioned in this MS Doc

If you want to assign role under your Communication Services from Portal, follow below steps:

Go to Azure Portal -> Your Communication Service -> Access control (IAM) -> Add role assignment

enter image description here

Assign Contributor role to the service principal like this:

enter image description here

Reference: Azure Active Directory in Communication Services | Microsoft

Sridevi
  • 10,599
  • 1
  • 4
  • 17
  • Thank you for your answer! I tried to add my name as a Contributor but it didn't work (same error message). I guess it has to be the service principal. Where do I find the current service principal name? – nop Feb 23 '23 at 18:15
  • https://i.imgur.com/ki1z1W0.png – nop Feb 23 '23 at 19:01
  • How you created service principal? Via CLI or Portal? – Sridevi Feb 23 '23 at 23:34
  • Does it create one automatically when I created resource for Communication Services? If not, then I haven't created a service principal. – nop Feb 24 '23 at 06:24
  • Then what value you are passing in ClientID? – Sridevi Feb 24 '23 at 06:27
  • Create one service principal from CLI by following this **[MS Doc](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/identity/service-principal-from-cli#creating-an-azure-active-directory-registered-application)** – Sridevi Feb 24 '23 at 06:28
2

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.

This is a known problem that is now being discussed internally. We are aiming to add preauthorization for well-known apps such as Az CLI, AzurePowerShell, VS, VSCode.

  1. In the Azure portal, navigate to the Azure Communication Services resource that you want to use for sending SMS messages.
  2. Click on the "Access control (IAM)" tab in the left-hand menu.
  3. Click on the "Add role assignment" button
  4. Do what?

Assign a security principal (user, group, service principal, or managed identity) that has been assigned a role with the Microsoft.Communication/CommunicationServices/Write permission (e.g. Contributor role or a custom role):

Microsoft.Communication/CommunicationServices/Write permission

rocky
  • 7,506
  • 3
  • 33
  • 48
  • Thanks for your answer! When I press on "View my access" you can see the groups that were inherited https://i.imgur.com/IwX2pMG.png. My name is in that group (Type: User, User type: Member). When I open `Contributor`, it already has these permissions: https://i.imgur.com/XAQhmrT.png. So dunno what's wrong. – nop Feb 24 '23 at 09:34
  • what type of credential/principal type are you aiming to use? – rocky Feb 24 '23 at 11:52
  • asking because I see that you're trying initialize multiple types of credentials in the DefaultAzureCredentialOptions. do you really want to use all of them? I also see that you're setting ManagedIdentityClientId yet you're exluding it via ExcludeManagedIdentityCredential... – rocky Feb 24 '23 at 11:57
  • also, are you trying to configure local env or a remote env (in azure)? – rocky Feb 24 '23 at 11:58
  • I'm trying to configure a local development (in JetBrains Rider) – nop Feb 24 '23 at 14:13
  • The ones that you see are inherited and there is nothing I can do about them. – nop Feb 24 '23 at 14:13
  • 1
    For local development, I'd recommend configuring the [`EnvironmentCredential`](https://learn.microsoft.com/en-us/dotnet/api/azure.identity.environmentcredential?view=azure-dotnet) (part of the `DefaultAzureCredential`) with a [service principal](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal) and setting the `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET` properties. – rocky Feb 27 '23 at 13:40
  • @rocky - Appreciate if you can take a look at this: https://stackoverflow.com/questions/76170274/unable-to-send-email-from-local-machine-via-azure-communication-service-and-usin. Thanks. – Gaurav Mantri May 04 '23 at 09:11
1

As rocky reply, the role and permissions on Access control (IAM) with be provided in the document sometime.

For how to use Azure credential - the DefaultAzureCredential class - for user credential interaction login, service principal, managed identities credential,etc you can reference this answer. For now, just I granted role Contributor to able send email.

The design concept of DefaultAzureCredential class is that you can use a very simple source code for many different scenarios of deployment. The actual credential (user account, service principal, manage identity,etc) will be setup when deployment and no source code changes.

Tho Ho
  • 687
  • 10
  • 13