Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
For security reasons, your server might host in a tenant independent from your Azure SignalR Service resource. Because managed identity can't be used across tenants, you need to register an application in tenant A and then provision it as an enterprise application in tenant B. This article helps you create an application in tenant A and use it to connect to an Azure SignalR Service resource in tenant B.
The first step is to create a multitenant application. For more information, see Quickstart: Register an application in Microsoft Entra ID.
If you already have a single tenant application, follow the instructions in Convert a single-tenant app to multitenant on Microsoft Entra ID.
There are four account types:
- Accounts in this organizational directory
- Accounts in any organizational directory
- Accounts in any organizational directory and personal Microsoft accounts
- Personal Microsoft accounts
Be sure to select either the second type or the third type when you create the application.
.
Make a note of the application (client) ID and the directory (tenant) ID for use in the following steps.
You can't assign the role to the application registered in other tenants. You have to provision it as an external enterprise application in tenant B. If you need more information, you can learn about the differences between app registration and enterprise applications.
In brief, the enterprise application is a service principal and the app registration isn't. The enterprise application inherits certain properties from the application object, such as the application (client) ID.
A default service principal is created in the tenant where the app is registered. For other tenants, you need to provision the app to get an enterprise application service principal. For more information, see Create an enterprise application from a multitenant application in Microsoft Entra ID.
Enterprise applications in different tenants have different directory (tenant) IDs, but they share the same application (client) ID.
After you have the enterprise application provisioned in your tenant B, you can assign roles to it.
The following steps describe how to assign a SignalR App Server role to a service principal or a managed identity for an Azure SignalR Service resource. For detailed steps, see Assign Azure roles by using the Azure portal.
Note
You can assign a role to any scope, including management group, subscription, resource group, or single resource. To learn more about scope, see Understand scope for Azure RBAC.
In the Azure portal, go to your Azure SignalR Service resource.
On the left pane, select Access control (IAM).
Select Add > Add role assignment.
On the Role tab, select SignalR App Server. Other Azure SignalR Service built-in roles depend on your scenario.
Role Description Use case SignalR App Server Access to the APIs that create server connections and generate keys. Most commonly used for an app server with an Azure SignalR resource running in Default mode. SignalR Service Owner Full access to all data-plane APIs, including REST APIs, the APIs that create server connections, and the APIs that generate keys/tokens. Used for a negotiation server with an Azure SignalR Service resource running in Serverless mode. It requires both REST API permissions and authentication API permissions. SignalR REST API Owner Full access to data-plane REST APIs. Used for the Azure SignalR Management SDK to manage connections and groups, but it doesn't make server connections or handle negotiation requests. SignalR REST API Reader Read-only access to data-plane REST APIs. Used when you write a monitoring tool that calls read-only REST APIs. Select Next.
For Microsoft Entra application:
- In the Assign access to row, select User, group, or service principal.
- In the Members row, choose select members, and then choose the identity in the pop-up window.
For managed identity for Azure resources:
- In the Assign access to row, select Managed identity.
- In the Members row, choose select members, and then choose the application in the pop-up window.
Select Next.
Review your assignment, and then select Review + assign to confirm the role assignment.
Important
Newly added role assignments might take up to 30 minutes to propagate.
To learn more about how to assign and manage Azure roles, see:
- Assign Azure roles by using the Azure portal
- Assign Azure roles by using the REST API
- Assign Azure roles by using Azure PowerShell
- Assign Azure roles by using the Azure CLI
- Assign Azure roles by using Azure Resource Manager templates
An application uses three different types of credentials to authenticate itself:
- Certificates
- Client secrets
- Federated identity
We strongly recommend that you use certificates or client secrets to make cross-tenant requests.
- The
tenantId
parameter is the ID of your tenant B. - The
clientId
parameters in both tenants are equal. - The
clientSecret
andclientCert
parameters are configured in tenant A. For more information, see Add credentials.
If you aren't sure about your tenant ID, see Find your Microsoft Entra tenant
services.AddSignalR().AddAzureSignalR(option =>
{
var credential1 = new ClientSecretCredential("tenantId", "clientId", "clientSecret", new TokenCredentialOptions { AuthorityHost=AzureAuthorityHosts.AzureChina});
var credential2 = new ClientCertificateCredential("tenantId", "clientId", "path-to-cert", new TokenCredentialOptions { AuthorityHost=AzureAuthorityHosts.AzureChina});
option.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint(new Uri("https://<resource1>.signalr.azure.cn"), credential1),
new ServiceEndpoint(new Uri("https://<resource2>.signalr.azure.cn"), credential2),
};
});
For security reasons, certificates and client secrets might be disabled in your subscription. In this case, you need to either use an external identity provider or try the preview support for managed identity. For more information, see:
- Configure an app to trust an external identity provider
- Configure an application to trust a managed identity (preview)
When you use managed identity as an identity provider, the code looks like the following example:
- The
tenantId
parameter is the ID of your tenant B. - The
clientId
parameters in both tenants are equal.
services.AddSignalR().AddAzureSignalR(option =>
{
var msiCredential = new ManagedIdentityCredential("msiClientId");
var credential = new ClientAssertionCredential("tenantId", "appClientId", async (ctoken) =>
{
// Entra ID China operated by 21Vianet: api://AzureADTokenExchangeChina
var request = new TokenRequestContext([$"api://AzureADTokenExchangeChina/.default"]);
var response = await msiCredential.GetTokenAsync(request, ctoken).ConfigureAwait(false);
return response.Token;
});
option.Endpoints = [
new ServiceEndpoint(new Uri(), "https://<resource>.signalr.azure.cn"), credential);
];
});
When you use external identity providers, the code looks like the following example:
services.AddSignalR().AddAzureSignalR(option =>
{
var credential = new ClientAssertionCredential("tenantId", "appClientId", async (ctoken) =>
{
// Find your own way to get a token from the external identity provider.
// The audience of the token should be "api://AzureADTokenExchangeChina" because it is the recommended value.
return "TheTokenYouGetFromYourExternalIdentityProvider";
});
option.Endpoints = [
new ServiceEndpoint(new Uri(), "https://<resource>.signalr.azure.cn"), credential);
];
});
Debugging token acquisition with the Azure SignalR Service SDK is a challenge because it depends on the token results. We recommend that you test the token acquisition process locally before you integrate with the Azure SignalR Service SDK.
var assertion = new ClientAssertionCredential("tenantId", "appClientId", async (ctoken) =>
{
// Find your own way to get a token from the external identity provider.
// The audience of the token should be "api://AzureADTokenExchangeChina" because it is the recommended value.
return TheTokenYouGetFromYourExternalIdentityProvider;
});
var request = new TokenRequestContext(["https://signalr.azure.cn/.default");
var token = await assertion.GetTokenAsync(assertion);
Console.log(token.Token);
The key point is to use an inner credential to get a clientAssertion
parameter from api://AzureADTokenExchangeChina
or other trusted identity platforms. Then use it to exchange for a token with the https://signalr.azure.cn/.default
audience to access your resource.
Your goal is to get a token with the following claims. Use jwt.io to help you decode the token:
- oid: The value should be equal to your enterprise application object ID. If you don't know where to get it, see Retrieve an enterprise object ID.
- tid: The value should be equal to the directory ID of your tenant B. If you aren't sure about your tenant ID, see Find your Microsoft Entra tenant.
- audience: The audience must be
https://signalr.azure.cn/.default
to access Azure SignalR Service resources.