Skip to content

Commit d1d9ad3

Browse files
authored
Merge branch 'dev' into tefa/update-swagger-to-20221101
2 parents e214822 + 0ee1765 commit d1d9ad3

File tree

56 files changed

+836
-519
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+836
-519
lines changed

.azure/pipelines/release.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ extends:
110110
inputs:
111111
version: 7.x
112112
performMultiLevelLookup: true
113+
- task: UseDotNet@2
114+
displayName: Add 8.x
115+
inputs:
116+
version: 8.x
117+
performMultiLevelLookup: true
113118
- ${{ if or( eq(parameters.isFinalBuild, false), eq(parameters.releaseSDKCore, true)) }}:
114119
- task: DotNetCoreCLI@2
115120
displayName: dotnet build AzureSignalR.sln

.github/workflows/osx.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: macOS-latest
1414
strategy:
1515
matrix:
16-
dotnet-version: [ '7.0.x', '6.0.x' ]
16+
dotnet-version: [ '8.0.x', '7.0.x', '6.0.x' ]
1717
steps:
1818
- uses: actions/checkout@v4
1919
- uses: dorny/paths-filter@v2
@@ -43,7 +43,7 @@ jobs:
4343
run: dotnet --version
4444
- name: Build with dotnet
4545
run: |
46-
if [ "${{ matrix.dotnet-version }}" = "7.0.x" ]; then
46+
if [ "${{ matrix.dotnet-version }}" != "6.0.x" ]; then
4747
dotnet sln AzureSignalR.sln remove test/Microsoft.Azure.SignalR.Protocols.Tests/Microsoft.Azure.SignalR.Protocols.Tests.csproj
4848
dotnet sln AzureSignalR.sln remove test/Microsoft.Azure.SignalR.Emulator.Tests/Microsoft.Azure.SignalR.Emulator.Tests.csproj
4949
dotnet sln AzureSignalR.sln remove test/Microsoft.Azure.SignalR.Management.Tests/Microsoft.Azure.SignalR.Management.Tests.csproj

.github/workflows/ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
strategy:
1515
matrix:
16-
dotnet-version: [ '7.0.x', '6.0.x' ]
16+
dotnet-version: [ '8.0.x', '7.0.x', '6.0.x' ]
1717
steps:
1818
- uses: actions/checkout@v4
1919
- uses: dorny/paths-filter@v2

.github/workflows/windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: [windows-latest]
1414
strategy:
1515
matrix:
16-
dotnet-version: [ '7.0.x', '6.0.x' ]
16+
dotnet-version: [ '8.0.x', '7.0.x', '6.0.x' ]
1717
steps:
1818
- uses: actions/checkout@v4
1919
- uses: dorny/paths-filter@v2

src/Microsoft.Azure.SignalR.AspNet/EndpointProvider/ServiceEndpointProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ public string GetServerEndpoint(string hubName)
9595

9696
public IAccessTokenProvider GetServerAccessTokenProvider(string hubName, string serverId)
9797
{
98-
if (_accessKey is AadAccessKey aadAccessKey)
98+
if (_accessKey is AccessKeyForMicrosoftEntra key)
9999
{
100-
return new AadTokenProvider(aadAccessKey);
100+
return new MicrosoftEntraTokenProvider(key);
101101
}
102102
else if (_accessKey is not null)
103103
{

src/Microsoft.Azure.SignalR.Common/Auth/AadTokenProvider.cs renamed to src/Microsoft.Azure.SignalR.Common/Auth/MicrosoftEntraTokenProvider.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
namespace Microsoft.Azure.SignalR
88
{
9-
internal class AadTokenProvider : IAccessTokenProvider
9+
internal class MicrosoftEntraTokenProvider : IAccessTokenProvider
1010
{
11-
private readonly AadAccessKey _accessKey;
11+
private readonly AccessKeyForMicrosoftEntra _accessKey;
1212

13-
public AadTokenProvider(AadAccessKey accessKey)
13+
public MicrosoftEntraTokenProvider(AccessKeyForMicrosoftEntra accessKey)
1414
{
1515
_accessKey = accessKey ?? throw new ArgumentNullException(nameof(accessKey));
1616
}
1717

18-
public Task<string> ProvideAsync() => _accessKey.GenerateAadTokenAsync();
18+
public Task<string> ProvideAsync() => _accessKey.GetMicrosoftEntraTokenAsync();
1919
}
2020
}

src/Microsoft.Azure.SignalR.Common/Endpoints/AadAccessKey.cs renamed to src/Microsoft.Azure.SignalR.Common/Endpoints/AccessKeyForMicrosoftEntra.cs

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,43 @@
1717

1818
namespace Microsoft.Azure.SignalR
1919
{
20-
internal class AadAccessKey : AccessKey
20+
internal class AccessKeyForMicrosoftEntra : AccessKey
2121
{
22-
internal const int AuthorizeIntervalInMinute = 55;
22+
internal static readonly TimeSpan GetAccessKeyTimeout = TimeSpan.FromSeconds(100);
2323

24-
internal const int AuthorizeMaxRetryTimes = 3;
24+
private const int GetAccessKeyIntervalInMinute = 55;
2525

26-
internal const int AuthorizeRetryIntervalInSec = 3;
26+
private const int GetAccessKeyMaxRetryTimes = 3;
2727

28-
internal const int GetTokenMaxRetryTimes = 3;
29-
30-
internal static readonly TimeSpan AuthorizeTimeout = TimeSpan.FromSeconds(100);
28+
private const int GetMicrosoftEntraTokenMaxRetryTimes = 3;
3129

3230
private const string DefaultScope = "https://signalr.azure.com/.default";
3331

34-
private static readonly TimeSpan AuthorizeInterval = TimeSpan.FromMinutes(AuthorizeIntervalInMinute);
35-
3632
private static readonly TokenRequestContext DefaultRequestContext = new TokenRequestContext(new string[] { DefaultScope });
3733

38-
private static readonly TimeSpan AuthorizeIntervalWhenFailed = TimeSpan.FromMinutes(5);
34+
private static readonly TimeSpan GetAccessKeyInterval = TimeSpan.FromMinutes(GetAccessKeyIntervalInMinute);
3935

40-
private static readonly TimeSpan AuthorizeRetryInterval = TimeSpan.FromSeconds(AuthorizeRetryIntervalInSec);
36+
private static readonly TimeSpan GetAccessKeyIntervalWhenUnauthorized = TimeSpan.FromMinutes(5);
37+
38+
private static readonly TimeSpan GetAccessKeyRetryInterval = TimeSpan.FromSeconds(3);
4139

4240
private readonly TaskCompletionSource<object> _initializedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
4341

4442
private volatile bool _isAuthorized = false;
4543

44+
private Exception _lastException;
45+
4646
private DateTime _lastUpdatedTime = DateTime.MinValue;
4747

48-
public bool Authorized
48+
public bool IsAuthorized
4949
{
5050
get => _isAuthorized;
5151
private set
5252
{
53+
if (value)
54+
{
55+
_lastException = null;
56+
}
5357
_lastUpdatedTime = DateTime.UtcNow;
5458
_isAuthorized = value;
5559
_initializedTcs.TrySetResult(null);
@@ -58,23 +62,23 @@ private set
5862

5963
public TokenCredential TokenCredential { get; }
6064

61-
internal string AuthorizeUrl { get; }
65+
internal string GetAccessKeyUrl { get; }
6266

63-
internal bool HasExpired => DateTime.UtcNow - _lastUpdatedTime > TimeSpan.FromMinutes(AuthorizeIntervalInMinute * 2);
67+
internal bool HasExpired => DateTime.UtcNow - _lastUpdatedTime > TimeSpan.FromMinutes(GetAccessKeyIntervalInMinute * 2);
6468

6569
private Task<object> InitializedTask => _initializedTcs.Task;
6670

67-
public AadAccessKey(Uri endpoint, TokenCredential credential, Uri serverEndpoint = null) : base(endpoint)
71+
public AccessKeyForMicrosoftEntra(Uri endpoint, TokenCredential credential, Uri serverEndpoint = null) : base(endpoint)
6872
{
6973
var authorizeUri = (serverEndpoint ?? endpoint).Append("/api/v1/auth/accessKey");
70-
AuthorizeUrl = authorizeUri.AbsoluteUri;
74+
GetAccessKeyUrl = authorizeUri.AbsoluteUri;
7175
TokenCredential = credential;
7276
}
7377

74-
public virtual async Task<string> GenerateAadTokenAsync(CancellationToken ctoken = default)
78+
public virtual async Task<string> GetMicrosoftEntraTokenAsync(CancellationToken ctoken = default)
7579
{
7680
Exception latest = null;
77-
for (var i = 0; i < GetTokenMaxRetryTimes; i++)
81+
for (var i = 0; i < GetMicrosoftEntraTokenMaxRetryTimes; i++)
7882
{
7983
try
8084
{
@@ -101,14 +105,9 @@ public override async Task<string> GenerateAccessTokenAsync(
101105
if (task == InitializedTask || InitializedTask.IsCompleted)
102106
{
103107
await task;
104-
if (Authorized)
105-
{
106-
return await base.GenerateAccessTokenAsync(audience, claims, lifetime, algorithm);
107-
}
108-
else
109-
{
110-
throw new AzureSignalRAccessTokenNotAuthorizedException("The given AzureAD identity don't have the permission to generate access token.");
111-
}
108+
return IsAuthorized
109+
? await base.GenerateAccessTokenAsync(audience, claims, lifetime, algorithm)
110+
: throw new AzureSignalRAccessTokenNotAuthorizedException(TokenCredential.GetType().Name, _lastException);
112111
}
113112
else
114113
{
@@ -119,47 +118,42 @@ public override async Task<string> GenerateAccessTokenAsync(
119118
internal void UpdateAccessKey(string kid, string accessKey)
120119
{
121120
Key = new Tuple<string, string>(kid, accessKey);
122-
Authorized = true;
121+
IsAuthorized = true;
123122
}
124123

125124
internal async Task UpdateAccessKeyAsync(CancellationToken ctoken = default)
126125
{
127126
var delta = DateTime.UtcNow - _lastUpdatedTime;
128-
if (Authorized && delta < AuthorizeInterval)
127+
if (IsAuthorized && delta < GetAccessKeyInterval)
129128
{
130129
return;
131130
}
132-
else if (!Authorized && delta < AuthorizeIntervalWhenFailed)
131+
else if (!IsAuthorized && delta < GetAccessKeyIntervalWhenUnauthorized)
133132
{
134133
return;
135134
}
136-
await AuthorizeWithRetryAsync(ctoken);
137-
}
138135

139-
private async Task AuthorizeWithRetryAsync(CancellationToken ctoken = default)
140-
{
141-
Exception latest = null;
142-
for (var i = 0; i < AuthorizeMaxRetryTimes; i++)
136+
for (var i = 0; i < GetAccessKeyMaxRetryTimes; i++)
143137
{
144-
var source = new CancellationTokenSource(AuthorizeTimeout);
138+
var source = new CancellationTokenSource(GetAccessKeyTimeout);
145139
var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(source.Token, ctoken);
146140
try
147141
{
148-
var token = await GenerateAadTokenAsync(linkedSource.Token);
149-
await AuthorizeWithTokenAsync(token, linkedSource.Token);
142+
var token = await GetMicrosoftEntraTokenAsync(linkedSource.Token);
143+
await GetAccessKeyInternalAsync(token, linkedSource.Token);
150144
return;
151145
}
152146
catch (OperationCanceledException e)
153147
{
154-
latest = e;
148+
_lastException = e;
155149
break;
156150
}
157151
catch (Exception e)
158152
{
159-
latest = e;
153+
_lastException = e;
160154
try
161155
{
162-
await Task.Delay(AuthorizeRetryInterval, ctoken);
156+
await Task.Delay(GetAccessKeyRetryInterval, ctoken);
163157
}
164158
catch (OperationCanceledException)
165159
{
@@ -168,13 +162,12 @@ private async Task AuthorizeWithRetryAsync(CancellationToken ctoken = default)
168162
}
169163
}
170164

171-
Authorized = false;
172-
throw latest;
165+
IsAuthorized = false;
173166
}
174167

175-
private async Task AuthorizeWithTokenAsync(string accessToken, CancellationToken ctoken = default)
168+
private async Task GetAccessKeyInternalAsync(string accessToken, CancellationToken ctoken = default)
176169
{
177-
var api = new RestApiEndpoint(AuthorizeUrl, accessToken);
170+
var api = new RestApiEndpoint(GetAccessKeyUrl, accessToken);
178171

179172
await new RestClient().SendAsync(
180173
api,

src/Microsoft.Azure.SignalR.Common/Endpoints/AccessKeySynchronizer.Log.cs

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/Microsoft.Azure.SignalR.Common/Endpoints/AccessKeySynchronizer.cs

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,24 @@
1111

1212
namespace Microsoft.Azure.SignalR
1313
{
14-
internal partial class AccessKeySynchronizer : IAccessKeySynchronizer, IDisposable
14+
internal sealed class AccessKeySynchronizer : IAccessKeySynchronizer, IDisposable
1515
{
1616
private readonly ConcurrentDictionary<ServiceEndpoint, object> _endpoints = new ConcurrentDictionary<ServiceEndpoint, object>(ReferenceEqualityComparer.Instance);
1717

1818
private readonly ILoggerFactory _factory;
1919

2020
private readonly TimerAwaitable _timer = new TimerAwaitable(TimeSpan.Zero, TimeSpan.FromMinutes(1));
2121

22-
public AccessKeySynchronizer(
23-
ILoggerFactory loggerFactory
24-
) : this(loggerFactory, true)
22+
internal IEnumerable<AccessKeyForMicrosoftEntra> AccessKeyForMicrosoftEntraList => _endpoints.Select(e => e.Key.AccessKey).OfType<AccessKeyForMicrosoftEntra>();
23+
24+
public AccessKeySynchronizer(ILoggerFactory loggerFactory) : this(loggerFactory, true)
2525
{
2626
}
2727

2828
/// <summary>
29-
/// For test only.
29+
/// Test only.
3030
/// </summary>
31-
internal AccessKeySynchronizer(
32-
ILoggerFactory loggerFactory,
33-
bool start
34-
)
31+
internal AccessKeySynchronizer(ILoggerFactory loggerFactory, bool start)
3532
{
3633
if (start)
3734
{
@@ -42,9 +39,9 @@ bool start
4239

4340
public void AddServiceEndpoint(ServiceEndpoint endpoint)
4441
{
45-
if (endpoint.AccessKey is AadAccessKey aadKey)
42+
if (endpoint.AccessKey is AccessKeyForMicrosoftEntra key)
4643
{
47-
_ = UpdateAccessKeyAsync(aadKey);
44+
_ = key.UpdateAccessKeyAsync();
4845
}
4946
_endpoints.TryAdd(endpoint, null);
5047
}
@@ -64,8 +61,6 @@ public void UpdateServiceEndpoints(IEnumerable<ServiceEndpoint> endpoints)
6461

6562
internal int ServiceEndpointsCount() => _endpoints.Count;
6663

67-
internal IEnumerable<AadAccessKey> FilterAadAccessKeys() => _endpoints.Select(e => e.Key.AccessKey).OfType<AadAccessKey>();
68-
6964
private async Task UpdateAccessKeyAsync()
7065
{
7166
using (_timer)
@@ -74,28 +69,14 @@ private async Task UpdateAccessKeyAsync()
7469

7570
while (await _timer)
7671
{
77-
foreach (var key in FilterAadAccessKeys())
72+
foreach (var key in AccessKeyForMicrosoftEntraList)
7873
{
79-
_ = UpdateAccessKeyAsync(key);
74+
_ = key.UpdateAccessKeyAsync();
8075
}
8176
}
8277
}
8378
}
8479

85-
private async Task UpdateAccessKeyAsync(AadAccessKey key)
86-
{
87-
var logger = _factory.CreateLogger<AadAccessKey>();
88-
try
89-
{
90-
await key.UpdateAccessKeyAsync();
91-
Log.SucceedToAuthorizeAccessKey(logger, key.AuthorizeUrl);
92-
}
93-
catch (Exception e)
94-
{
95-
Log.FailedToAuthorizeAccessKey(logger, key.AuthorizeUrl, e);
96-
}
97-
}
98-
9980
private sealed class ReferenceEqualityComparer : IEqualityComparer<ServiceEndpoint>
10081
{
10182
internal static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer();

src/Microsoft.Azure.SignalR.Common/Endpoints/ServiceEndpoint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ internal AccessKey AccessKey
8686
{
8787
lock (_lock)
8888
{
89-
_accessKey ??= new AadAccessKey(_serviceEndpoint, _tokenCredential, ServerEndpoint);
89+
_accessKey ??= new AccessKeyForMicrosoftEntra(_serviceEndpoint, _tokenCredential, ServerEndpoint);
9090
}
9191
}
9292
return _accessKey;

0 commit comments

Comments
 (0)