Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class CommunicationRecordedTestSanitizer : RecordedTestSanitizer
{
private static readonly Regex _azureResourceRegEx = new Regex(@"[^/]+?(?=(.communication.azure))", RegexOptions.Compiled);
private static readonly Regex _identityInRouteRegEx = new Regex(@"(?<=identities/)([^/]+)", RegexOptions.Compiled);
private static readonly Regex _turnInRouteRegEx = new Regex(@"(?<=turn/)([^/]+)", RegexOptions.Compiled);
private static readonly Regex _phoneNumberRegEx = new Regex(@"[\\+]?[0-9]{11,15}", RegexOptions.Compiled);
private static readonly Regex _guidRegEx = new Regex(@"(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}", RegexOptions.Compiled);

Expand All @@ -28,6 +29,9 @@ public CommunicationRecordedTestSanitizer() : base()
JsonPathSanitizers.Add("$..phonePlanId");
JsonPathSanitizers.Add("$..phonePlanGroupId");
JsonPathSanitizers.Add("$..phonePlanIds[:]");
JsonPathSanitizers.Add("$..urls");
JsonPathSanitizers.Add("$..username");
JsonPathSanitizers.Add("$..credential");
}

public override void SanitizeHeaders(IDictionary<string, string[]> headers)
Expand Down Expand Up @@ -76,6 +80,7 @@ internal static string SanitizeConnectionString(string connectionString)
public override string SanitizeUri(string uri)
{
uri = SanitizeAzureResource(_identityInRouteRegEx.Replace(uri, SanitizeValue.ToLower()));
uri = SanitizeAzureResource(_turnInRouteRegEx.Replace(uri, SanitizeValue.ToLower()));
return _guidRegEx.Replace(uri, SanitizeValue);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public CommunicationIdentityClient(System.Uri endpoint, Azure.Core.TokenCredenti
public virtual System.Threading.Tasks.Task<Azure.Response> DeleteUserAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<Azure.Core.AccessToken> IssueToken(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Collections.Generic.IEnumerable<Azure.Communication.Identity.CommunicationTokenScope> scopes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Core.AccessToken>> IssueTokenAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Collections.Generic.IEnumerable<Azure.Communication.Identity.CommunicationTokenScope> scopes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response<Azure.Communication.Identity.Models.CommunicationTurnCredentialsResponse> IssueTurnCredentials(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response<Azure.Communication.Identity.Models.CommunicationTurnCredentialsResponse>> IssueTurnCredentialsAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response RevokeTokens(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Response> RevokeTokensAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
Expand Down Expand Up @@ -45,3 +47,19 @@ public enum ServiceVersion
public override string ToString() { throw null; }
}
}
namespace Azure.Communication.Identity.Models
{
public partial class CommunicationTurnCredentialsResponse
{
internal CommunicationTurnCredentialsResponse() { }
public System.DateTimeOffset ExpiresOn { get { throw null; } }
public System.Collections.Generic.IReadOnlyList<Azure.Communication.Identity.Models.CommunicationTurnServer> TurnServers { get { throw null; } }
}
public partial class CommunicationTurnServer
{
internal CommunicationTurnServer() { }
public string Credential { get { throw null; } }
public string Urls { get { throw null; } }
public string Username { get { throw null; } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ To get started you will need to have an Azure Subscription. Once you have this y

This client library allows to do following operations:
- Generate user tokens that allows the holders to access Azure Communication Services.
- Purchase, configure and release phone numbers.
- Generate TURN server credentials that allows the holders to get access to a TURN server for media relay.

#### You can find samples for each of these functions below.
- Generate user tokens [synchronously][sample_identity] or [asynchronously][sample_identity_async]
- Generate user tokens and TURN credentials [synchronously][sample_identity] or [asynchronously][sample_identity_async]

<!-- LINKS -->
[sample_identity]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClient.md
[sample_identity_async]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClientAsync.md
[
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ Console.WriteLine($"Token: {token}");
Console.WriteLine($"Expires On: {expiresOn}");
```

## Generate TURN credentials

The example code snippet below shows how to generate TURN credentials for an Azure Communication user that was created following the steps above.
A set of TURN credentials are returned for the user. Each TURN credential consists of a url for a TURN server, its corresponding username and a credential.

Every set of TURN credentials is stamped with an expiry date. Once the credentials are expired, you can renew the token by calling the same method.

```C# Snippet:CreateTURNTokenAsync
Response<CommunicationTurnCredentialsResponse> turnTokenResponse = await client.IssueTurnCredentialsAsync(user);
DateTimeOffset turnTokenExpiresOn = turnTokenResponse.Value.ExpiresOn;
IReadOnlyList<CommunicationTurnServer> turnServers = turnTokenResponse.Value.TurnServers;
Console.WriteLine($"Expires On: {turnTokenExpiresOn}");
foreach (CommunicationTurnServer turnServer in turnServers)
{
Console.WriteLine($"TURN Url: {turnServer.Urls}");
Console.WriteLine($"TURN Username: {turnServer.Username}");
Console.WriteLine($"TURN Credential: {turnServer.Credential}");
}
```

<!--
To see the full example source files, see:
* [Generate user token][GenerateUserTokenCode]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,26 @@ Console.WriteLine($"Token: {token}");
Console.WriteLine($"Expires On: {expiresOn}");
```

## Generate TURN credentials

The example code snippet below shows how to generate TURN credentials for an Azure Communication user that was created following the steps above.
A set of TURN credentials are returned for the user. Each TURN credential consists of a url for a TURN server, its corresponding username and a credential.

Every set of TURN credentials is stamped with an expiry date. Once the credentials are expired, you can renew the token by calling the same method.

```C# Snippet:CreateTURNTokenAsync
Response<CommunicationTurnCredentialsResponse> turnTokenResponse = await client.IssueTurnCredentialsAsync(user);
DateTimeOffset turnTokenExpiresOn = turnTokenResponse.Value.ExpiresOn;
IReadOnlyList<CommunicationTurnServer> turnServers = turnTokenResponse.Value.TurnServers;
Console.WriteLine($"Expires On: {turnTokenExpiresOn}");
foreach (CommunicationTurnServer turnServer in turnServers)
{
Console.WriteLine($"TURN Url: {turnServer.Urls}");
Console.WriteLine($"TURN Username: {turnServer.Username}");
Console.WriteLine($"TURN Credential: {turnServer.Credential}");
}
```

<!--
To see the full example source files, see:
* [Generate user token][GenerateUserTokenCode]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ namespace Azure.Communication.Identity
public class CommunicationIdentityClient
{
private readonly ClientDiagnostics _clientDiagnostics;
private readonly HttpPipeline _pipeline;
private readonly string _endpoint;
internal CommunicationIdentityRestClient RestClient { get; }
internal CommunicationIdentityRestClient RestClientForTurn { get; }

/// <summary> Initializes a new instance of <see cref="CommunicationIdentityClient"/>.</summary>
/// <param name="endpoint">The URI of the Azure Communication Services resource.</param>
Expand Down Expand Up @@ -62,28 +65,37 @@ public CommunicationIdentityClient(Uri endpoint, TokenCredential tokenCredential
private CommunicationIdentityClient(CommunicationIdentityClientOptions options, ConnectionString connectionString)
{
_clientDiagnostics = new ClientDiagnostics(options);
_pipeline = options.BuildHttpPipeline(connectionString);
_endpoint = connectionString.GetRequired("endpoint");
RestClient = new CommunicationIdentityRestClient(
_clientDiagnostics,
options.BuildHttpPipeline(connectionString),
connectionString.GetRequired("endpoint"));
_pipeline,
_endpoint,
apiVersion: "2021-03-07");
}

private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOptions options, AzureKeyCredential credential)
{
_clientDiagnostics = new ClientDiagnostics(options);
_pipeline = options.BuildHttpPipeline(credential);
_endpoint = endpoint.AbsoluteUri;
RestClient = new CommunicationIdentityRestClient(
_clientDiagnostics,
options.BuildHttpPipeline(credential),
endpoint.AbsoluteUri);
_pipeline,
_endpoint,
apiVersion: "2021-03-07");
}

private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOptions options, TokenCredential tokenCredential)
{
_clientDiagnostics = new ClientDiagnostics(options);
_pipeline = options.BuildHttpPipeline(tokenCredential);
_endpoint = endpoint.AbsoluteUri;
RestClient = new CommunicationIdentityRestClient(
_clientDiagnostics,
options.BuildHttpPipeline(tokenCredential),
endpoint.AbsoluteUri);
_pipeline,
_endpoint,
apiVersion: "2021-03-07");
}

/// <summary>Initializes a new instance of <see cref="CommunicationIdentityClient"/> for mocking.</summary>
Expand Down Expand Up @@ -290,6 +302,57 @@ public virtual async Task<Response> RevokeTokensAsync(CommunicationUserIdentifie
}
}

/// <summary>Issues a token for a <see cref="CommunicationUserIdentifier"/>.</summary>
/// <param name="communicationUser">The <see cref="CommunicationUserIdentifier"/> for whom to issue a token.</param>
/// <param name="cancellationToken">The cancellation token to use.</param>
/// <exception cref="RequestFailedException">The server returned an error.</exception>
public virtual Response<CommunicationTurnCredentialsResponse> IssueTurnCredentials(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default)
{
var RestClientForTurn = new CommunicationIdentityRestClient(
_clientDiagnostics,
_pipeline,
_endpoint,
apiVersion: "2021-12-12");

using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueTurnCredentials)}");
scope.Start();
try
{
Response<CommunicationTurnCredentialsResponse> response = RestClientForTurn.IssueTurnCredentials(communicationUser.Id, cancellationToken);
return response;
}
catch (Exception ex)
{
scope.Failed(ex);
throw;
}
}

/// <summary>Asynchronously issues a token for a <see cref="CommunicationUserIdentifier"/>.</summary>
/// <param name="communicationUser">The <see cref="CommunicationUserIdentifier"/> for whom to issue a token.</param>
/// <param name="cancellationToken">The cancellation token to use.</param>
public virtual async Task<Response<CommunicationTurnCredentialsResponse>> IssueTurnCredentialsAsync(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default)
{
var RestClientForTurn = new CommunicationIdentityRestClient(
_clientDiagnostics,
_pipeline,
_endpoint,
apiVersion: "2021-12-12");

using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueTurnCredentials)}");
scope.Start();
try
{
Response<CommunicationTurnCredentialsResponse> response = await RestClientForTurn.IssueTurnCredentialsAsync(communicationUser.Id, cancellationToken).ConfigureAwait(false);
return response;
}
catch (Exception ex)
{
scope.Failed(ex);
throw;
}
}

private static T AssertNotNull<T>(T argument, string argumentName)
where T : class
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading