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

[Communication] - Common - Adding TokenRefreshOptions to CommunicationTokenCredential ctor #17597

Merged
merged 16 commits into from
Dec 18, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
using System.Linq;
using System.Threading.Tasks;
using Azure.Communication.Administration.Models;
using Azure.Communication;
using Azure.Core;
using Azure.Core.TestFramework;
using Azure.Identity;
using NUnit.Framework;
using Azure.Core;
using Azure.Communication.Identity;

namespace Azure.Communication.Administration.Tests
{
Expand Down
2 changes: 1 addition & 1 deletion sdk/communication/Azure.Communication.Chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ For the generation of user access tokens, refer to [User Access Tokens][useracce
```C# Snippet:Azure_Communication_Chat_Tests_E2E_UsingStatements
using Azure.Communication.Administration;
using Azure.Communication.Administration.Models;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Communication.Chat;
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Azure.Communication.Chat
public partial class ChatClient
{
protected ChatClient() { }
public ChatClient(System.Uri endpointUrl, Azure.Communication.Identity.CommunicationTokenCredential communicationTokenCredential, Azure.Communication.Chat.ChatClientOptions? options = null) { }
public ChatClient(System.Uri endpointUrl, Azure.Communication.CommunicationTokenCredential communicationTokenCredential, Azure.Communication.Chat.ChatClientOptions? options = null) { }
public virtual Azure.Communication.Chat.ChatThreadClient CreateChatThread(string topic, System.Collections.Generic.IEnumerable<Azure.Communication.Chat.ChatThreadMember> members, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual System.Threading.Tasks.Task<Azure.Communication.Chat.ChatThreadClient> CreateChatThreadAsync(string topic, System.Collections.Generic.IEnumerable<Azure.Communication.Chat.ChatThreadMember> members, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public virtual Azure.Response DeleteChatThread(string threadId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Communication.Pipeline;
using Azure.Core;
using Azure.Core.Pipeline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Communication.Pipeline;
using Azure.Core;
using Azure.Core.Pipeline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#region Snippet:Azure_Communication_Chat_Tests_E2E_UsingStatements
using Azure.Communication.Administration;
using Azure.Communication.Administration.Models;
using Azure.Communication.Identity;
using Azure.Communication;
//@@ using Azure.Communication.Chat;
#endregion Snippet:Azure_Communication_Chat_Tests_E2E_UsingStatements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;
using System.Threading.Tasks;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Azure.Communication.Administration;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Core.TestFramework;

namespace Azure.Communication.Chat.Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Threading.Tasks;
using Azure.Communication.Administration;
using Azure.Communication.Administration.Models;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Threading.Tasks;
using Azure.Communication.Administration;
using Azure.Communication.Administration.Models;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Threading.Tasks;
using Azure.Communication.Administration;
using Azure.Communication.Administration.Models;
using Azure.Communication.Identity;
using Azure.Communication;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand Down
2 changes: 2 additions & 0 deletions sdk/communication/Azure.Communication.Common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## 1.0.0-beta.4 (Unreleased)
### Breaking Changes
- Renamed `CommunicationUserCredential` to `CommunicationTokenCredential`.
- Replace `CommunicationTokenCredential(bool refreshProactively, Func<CancellationToken, string> tokenRefresher,Func<CancellationToken, ValueTask<string>>? asyncTokenRefresher = null, string? initialToken = null)`
with `CommunicationTokenCredential(CommunicationTokenRefreshOptions tokenRefreshOptions)`.
- Renamed `PhoneNumber` to `PhoneNumberIdentifier`
- Renamed `CommunicationUser` to `CommunicationUserIdentifier `
- Renamed `CallingApplication` to `CallingApplicationIdentifier`
Expand Down
19 changes: 12 additions & 7 deletions sdk/communication/Azure.Communication.Common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,25 @@ previous token approaches expiry. Using this method, your requests are less like

```C# Snippet:CommunicationTokenCredential_CreateRefreshableWithoutInitialToken
using var tokenCredential = new CommunicationTokenCredential(
refreshProactively: true, // Indicates if the token should be proactively refreshed in the background or only on-demand
tokenRefresher: cancellationToken => FetchTokenForUserFromMyServer("bob@contoso.com", cancellationToken),
asyncTokenRefresher: cancellationToken => FetchTokenForUserFromMyServerAsync("bob@contoso.com", cancellationToken));
new CommunicationTokenRefreshOptions(
refreshProactively: true, // Indicates if the token should be proactively refreshed in the background or only on-demand
tokenRefresher: cancellationToken => FetchTokenForUserFromMyServer("bob@contoso.com", cancellationToken),
asyncTokenRefresher: cancellationToken => FetchTokenForUserFromMyServerAsync("bob@contoso.com", cancellationToken)
)
);
```

If you already have a token, you can optimize the token refreshing even further by passing that initial token:

```C# Snippet:CommunicationTokenCredential_CreateRefreshableWithInitialToken
string initialToken = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_USER_TOKEN");
using var tokenCredential = new CommunicationTokenCredential(
refreshProactively: true, // Indicates if the token should be proactively refreshed in the background or only on-demand
tokenRefresher: cancellationToken => FetchTokenForUserFromMyServer("bob@contoso.com", cancellationToken),
asyncTokenRefresher: cancellationToken => FetchTokenForUserFromMyServerAsync("bob@contoso.com", cancellationToken),
initialToken);
new CommunicationTokenRefreshOptions(
refreshProactively: true, // Indicates if the token should be proactively refreshed in the background or only on-demand
tokenRefresher: cancellationToken => FetchTokenForUserFromMyServer("bob@contoso.com", cancellationToken),
asyncTokenRefresher: cancellationToken => FetchTokenForUserFromMyServerAsync("bob@contoso.com", cancellationToken),
initialToken)
);
```

## Troubleshooting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ public abstract partial class CommunicationIdentifier
{
protected CommunicationIdentifier() { }
}
public sealed partial class CommunicationTokenCredential : System.IDisposable
{
public CommunicationTokenCredential(Azure.Communication.CommunicationTokenRefreshOptions tokenRefreshOptions) { }
public CommunicationTokenCredential(string token) { }
public void Dispose() { }
public Azure.Core.AccessToken GetToken(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask<Azure.Core.AccessToken> GetTokenAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public partial class CommunicationTokenRefreshOptions
{
public CommunicationTokenRefreshOptions(bool refreshProactively, System.Func<System.Threading.CancellationToken, string> tokenRefresher, System.Func<System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<string>>? asyncTokenRefresher, string? token = null) { }
}
public partial class CommunicationUserIdentifier : Azure.Communication.CommunicationIdentifier
{
public CommunicationUserIdentifier(string id) { }
Expand All @@ -26,14 +38,3 @@ public UnknownIdentifier(string id) { }
public string Id { get { throw null; } }
}
}
namespace Azure.Communication.Identity
{
public sealed partial class CommunicationTokenCredential : System.IDisposable
{
public CommunicationTokenCredential(bool refreshProactively, System.Func<System.Threading.CancellationToken, string> tokenRefresher, System.Func<System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<string>>? asyncTokenRefresher = null, string? initialToken = null) { }
public CommunicationTokenCredential(string userToken) { }
public void Dispose() { }
public Azure.Core.AccessToken GetToken(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask<Azure.Core.AccessToken> GetTokenAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
using System.Threading.Tasks;
using Azure.Core;

namespace Azure.Communication.Identity
namespace Azure.Communication
{
internal sealed class AutoRefreshTokenCredential : ITokenCredential
internal sealed class AutoRefreshTokenCredential : ICommunicationTokenCredential
{
private readonly ThreadSafeRefreshableAccessTokenCache _accessTokenCache;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,39 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.Communication;
using Azure.Core;

namespace Azure.Communication.Identity
namespace Azure.Communication
{
/// <summary>
/// The Azure Communication Services Token Credential.
/// </summary>
public sealed class CommunicationTokenCredential : IDisposable
{
private readonly ITokenCredential _tokenCredential;
private readonly ICommunicationTokenCredential _tokenCredential;
private bool _isDisposed;

/// <summary>
/// Initializes a new instance of <see cref="CommunicationTokenCredential"/>.
/// </summary>
/// <param name="userToken">User token acquired from Azure.Communication.Administration package.</param>
public CommunicationTokenCredential(string userToken)
=> _tokenCredential = new StaticTokenCredential(userToken);
/// <param name="token">User token acquired from Azure.Communication.Administration package.</param>
public CommunicationTokenCredential(string token)
=> _tokenCredential = new StaticTokenCredential(token);

/// <summary>
/// Initializes a new instance of <see cref="CommunicationTokenCredential"/> that automatically renews the token upon expiry or proactively prior to expiration to speed up the requests.
/// </summary>
/// <param name="refreshProactively">Indicates whether the token should be proactively renewed prior to expiry or renew on demand.</param>
/// <param name="tokenRefresher">The function that provides the token acquired from the configurtaion SDK.</param>
/// <param name="asyncTokenRefresher">The async function that provides the token acquired from the configurtaion SDK.</param>
/// <param name="initialToken">Optional token to initialize.</param>
public CommunicationTokenCredential(
bool refreshProactively,
Func<CancellationToken, string> tokenRefresher,
Func<CancellationToken, ValueTask<string>>? asyncTokenRefresher = null,
string? initialToken = null)
=> _tokenCredential = new AutoRefreshTokenCredential(
tokenRefresher,
asyncTokenRefresher ?? (cancellationToken => new ValueTask<string>(tokenRefresher(cancellationToken))),
initialToken,
refreshProactively);
/// <param name="tokenRefreshOptions">Options for how the token will be refreshed</param>
public CommunicationTokenCredential(CommunicationTokenRefreshOptions tokenRefreshOptions)
{
Argument.AssertNotNull(tokenRefreshOptions, nameof(tokenRefreshOptions));
_tokenCredential = new AutoRefreshTokenCredential(
tokenRefreshOptions.TokenRefresher,
tokenRefreshOptions.AsyncTokenRefresher ?? (cancellationToken => new ValueTask<string>(tokenRefreshOptions.TokenRefresher(cancellationToken))),
tokenRefreshOptions.Token,
tokenRefreshOptions.RefreshProactively);
}

/// <summary>
/// Gets an <see cref="AccessToken"/> for the user.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;

namespace Azure.Communication
{
/// <summary>
/// The Communication Token Refresh Options
/// </summary>
public class CommunicationTokenRefreshOptions
{
internal bool RefreshProactively { get; }
internal Func<CancellationToken, string> TokenRefresher { get; }
internal Func<CancellationToken, ValueTask<string>>? AsyncTokenRefresher { get; }
internal string? Token { get; }

/// <summary>
/// Initializes a new instance of <see cref="CommunicationTokenRefreshOptions"/>.
/// </summary>
/// <param name="refreshProactively">Indicates whether the token should be proactively renewed prior to expiry or renew on demand.</param>
/// <param name="tokenRefresher">The function that provides the token acquired from the configurtaion SDK.</param>
/// <param name="asyncTokenRefresher">The async function that provides the token acquired from the configurtaion SDK.</param>
/// <param name="token">Optional token value.</param>
public CommunicationTokenRefreshOptions(
bool refreshProactively,
Func<CancellationToken, string> tokenRefresher,
Func<CancellationToken, ValueTask<string>>? asyncTokenRefresher,
string? token = null)
{
RefreshProactively = refreshProactively;
TokenRefresher = tokenRefresher;
AsyncTokenRefresher = asyncTokenRefresher;
Token = token;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
using System.Threading.Tasks;
using Azure.Core;

namespace Azure.Communication.Identity
namespace Azure.Communication
{
internal interface ITokenCredential : IDisposable
internal interface ICommunicationTokenCredential : IDisposable
{
AccessToken GetToken(CancellationToken cancellationToken);
ValueTask<AccessToken> GetTokenAsync(CancellationToken cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Text.Json.Serialization;
using Azure.Core;

namespace Azure.Communication.Identity
namespace Azure.Communication
{
internal class JwtTokenParser
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
using System.Threading.Tasks;
using Azure.Core;

namespace Azure.Communication.Identity
namespace Azure.Communication
{
internal sealed class StaticTokenCredential : ITokenCredential
internal sealed class StaticTokenCredential : ICommunicationTokenCredential
{
private readonly AccessToken _accessToken;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using Azure.Core;
using Azure.Core.Pipeline;

namespace Azure.Communication.Identity
namespace Azure.Communication
{
/// <summary>
/// Represents a type that caches an access token,
Expand Down
Loading