Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IssueTurnCredentials API to Azure.Communication.Identity library (to be released in private preview) #1

Closed
wants to merge 11 commits into from
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