Skip to content

Commit a411eb0

Browse files
committed
Guard against scope nesting
1 parent 88c99cb commit a411eb0

3 files changed

Lines changed: 31 additions & 11 deletions

File tree

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,14 @@ public async Task CreateUserAsync(User user, string orgId)
201201

202202
```
203203

204+
ALWAYS ensure you dispose of the scope when finished.
205+
204206
There's a few limitations if you're using this functionality, as it uses `AsyncLocal` internally:
205207

206-
- Never use multiple client scopes at the same time, either with the same or different client types.
207-
- Never call any other client that utilizes `.AddAccessToken` within a client scope.
208+
- Never use multiple client scopes at the same time, either with the same or different client types. This will throw an exception.
209+
- Never call any other client that utilizes `.AddAccessToken` within a client scope. This may cause the wrong Organization ID/Name being used for a given request.
208210

209-
Doing any of the above is likely to result in hard to debug behaviour and may cause the wrong Organization ID/Name being used for a given request.
211+
If you have a use-case for either of these items, please open an issue with an example.
210212

211213
This functionality is marked as experimental, and you must `#pragma warning disable AUTH0_EXPERIMENTAL` to use it.
212214

src/Auth0Net.DependencyInjection/Organizations/OrganizationScopeFactory.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ public OrganizationScopeFactory(TClient client, HttpClientOrganizationAccessor a
4848
/// </returns>
4949
public OrganizationScope<TClient> CreateScope(string organization)
5050
{
51+
#if NET8_0_OR_GREATER
52+
ArgumentNullException.ThrowIfNull(organization);
53+
#endif
54+
if (!string.IsNullOrEmpty(_accessor.Organization))
55+
throw new InvalidOperationException(
56+
"Attempted to create a nested organization scope. This is unsupported. Please open an issue if you'd find this useful.");
57+
5158
_accessor.Organization = organization;
5259
return new OrganizationScope<TClient>(_client, _accessor);
5360
}

tests/Auth0Net.DependencyInjection.Tests/OrganizationScopeFactoryTests.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using Xunit;
77

88
namespace Auth0Net.DependencyInjection.Tests;
9-
9+
#pragma warning disable AUTH0_EXPERIMENTAL
1010
public class OrganizationScopeFactoryTests
1111
{
1212
[Fact]
@@ -15,10 +15,9 @@ public void OrganizationScopeFactory_ThrowsForAuthenticationApiClient()
1515
var client = A.Fake<IAuthenticationApiClient>();
1616
var accessor = new HttpClientOrganizationAccessor();
1717

18-
#pragma warning disable AUTH0_EXPERIMENTAL
1918
Assert.Throws<InvalidOperationException>(() =>
2019
new OrganizationScopeFactory<IAuthenticationApiClient>(client, accessor));
21-
#pragma warning restore AUTH0_EXPERIMENTAL
20+
2221
}
2322

2423
[Fact]
@@ -27,10 +26,22 @@ public void OrganizationScopeFactory_ThrowsForManagementApiClient()
2726
var client = A.Fake<IManagementApiClient>();
2827
var accessor = new HttpClientOrganizationAccessor();
2928

30-
#pragma warning disable AUTH0_EXPERIMENTAL
3129
Assert.Throws<InvalidOperationException>(() =>
3230
new OrganizationScopeFactory<IManagementApiClient>(client, accessor));
33-
#pragma warning restore AUTH0_EXPERIMENTAL
31+
}
32+
33+
[Fact]
34+
public void OrganizationScopeFactory_CreateScope_ThrowsInNestedScope()
35+
{
36+
var client = new TestClient();
37+
var accessor = new HttpClientOrganizationAccessor();
38+
39+
var factory = new OrganizationScopeFactory<TestClient>(client, accessor);
40+
var scope = factory.CreateScope("org-123");
41+
Assert.Throws<InvalidOperationException>(() => factory.CreateScope("org-123"));
42+
43+
scope.Dispose();
44+
Assert.Null(accessor.Organization);
3445
}
3546

3647
[Fact]
@@ -39,17 +50,17 @@ public void OrganizationScopeFactory_CreateScope_SetsOrganizationOnAccessorAndEx
3950
var client = new TestClient();
4051
var accessor = new HttpClientOrganizationAccessor();
4152

42-
#pragma warning disable AUTH0_EXPERIMENTAL
4353
var factory = new OrganizationScopeFactory<TestClient>(client, accessor);
4454
var scope = factory.CreateScope("org-123");
45-
#pragma warning restore AUTH0_EXPERIMENTAL
46-
55+
4756
Assert.Equal("org-123", accessor.Organization);
4857
Assert.Same(client, scope.Client);
4958

5059
scope.Dispose();
5160
Assert.Null(accessor.Organization);
5261
}
5362

63+
64+
5465
private sealed class TestClient { }
5566
}

0 commit comments

Comments
 (0)