Skip to content

Commit 44a9afd

Browse files
sander1095Aniruddh25RubenCerna2079
authored
Add more tests for EntraId/AzureAd providers (#2610)
## Why make this change? Closes #2407 This issue adds more tests for the `EntraId` authentication provider. `EntraId` already seemed to be supported, so no business logic was needed for this change. ## What is this change? Several tests have been added. ## How was this tested? - [x] Integration Tests - [x] Unit Tests ## Sample Request(s) Use `EntraId` and `AzureAd` providers like before. --------- Co-authored-by: Aniruddh Munde <[email protected]> Co-authored-by: RubenCerna2079 <[email protected]>
1 parent 6f4b622 commit 44a9afd

11 files changed

+118
-16
lines changed

src/Cli.Tests/ConfigureOptionsTests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ public void TestUpdateCorsAllowCredentialsHostSettings(bool allowCredentialsValu
512512
[DataRow("staticWebApps", DisplayName = "Update authentication.provider to StaticWebApps for Host.")]
513513
[DataRow("Appservice", DisplayName = "Update authentication.provider to AppService for Host.")]
514514
[DataRow("azuread", DisplayName = "Update authentication.provider to AzureAD for Host.")]
515+
[DataRow("entraid", DisplayName = "Update authentication.provider to EntraID for Host.")]
515516
public void TestUpdateAuthenticationProviderHostSettings(string authenticationProviderValue)
516517
{
517518
// Arrange -> all the setup which includes creating options.

src/Cli.Tests/EndToEndTests.cs

+7-4
Original file line numberDiff line numberDiff line change
@@ -459,19 +459,21 @@ public void TestUpdateCacheTtlRuntimeSettings(string ttl, bool isSuccess)
459459
/// neither EasyAuth or Simulator as Authentication provider.
460460
/// It checks correct generation of config with provider, audience and issuer.
461461
/// </summary>
462-
[TestMethod]
463-
public void TestVerifyAuthenticationOptions()
462+
[DataTestMethod]
463+
[DataRow("AzureAD")]
464+
[DataRow("EntraID")]
465+
public void TestVerifyAuthenticationOptions(string authenticationProvider)
464466
{
465467
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--database-type", "mssql",
466-
"--auth.provider", "AzureAD", "--auth.audience", "aud-xxx", "--auth.issuer", "issuer-xxx" };
468+
"--auth.provider", authenticationProvider, "--auth.audience", "aud-xxx", "--auth.issuer", "issuer-xxx" };
467469
Program.Execute(initArgs, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
468470

469471
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
470472
Assert.IsNotNull(runtimeConfig);
471473

472474
Assert.IsNotNull(runtimeConfig.Runtime);
473475
Assert.IsNotNull(runtimeConfig.Runtime.Host);
474-
Assert.AreEqual("AzureAD", runtimeConfig.Runtime.Host.Authentication?.Provider);
476+
Assert.AreEqual(authenticationProvider, runtimeConfig.Runtime.Host.Authentication?.Provider);
475477
Assert.AreEqual("aud-xxx", runtimeConfig.Runtime.Host.Authentication?.Jwt?.Audience);
476478
Assert.AreEqual("issuer-xxx", runtimeConfig.Runtime.Host.Authentication?.Jwt?.Issuer);
477479
}
@@ -1114,6 +1116,7 @@ public async Task TestExitOfRuntimeEngineWithInvalidConfig(
11141116
[DataRow("StaticWebApps", false)]
11151117
[DataRow("AppService", true)]
11161118
[DataRow("AzureAD", true)]
1119+
[DataRow("EntraID", true)]
11171120
public void TestBaseRouteIsConfigurableForSWA(string authProvider, bool isExceptionExpected)
11181121
{
11191122
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--host-mode", "development", "--database-type", "mssql",

src/Cli.Tests/InitTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ public void EnsureFailureOnReInitializingExistingConfig()
302302
[DataRow("AppService", null, null, DisplayName = "AppService with no audience and no issuer specified.")]
303303
[DataRow("Simulator", null, null, DisplayName = "Simulator with no audience and no issuer specified.")]
304304
[DataRow("AzureAD", "aud-xxx", "issuer-xxx", DisplayName = "AzureAD with both audience and issuer specified.")]
305+
[DataRow("EntraID", "aud-xxx", "issuer-xxx", DisplayName = "EntraID with both audience and issuer specified.")]
305306
public Task EnsureCorrectConfigGenerationWithDifferentAuthenticationProviders(
306307
string authenticationProvider,
307308
string? audience,
@@ -426,7 +427,7 @@ public Task GraphQLPathWithoutStartingSlashWillHaveItAdded()
426427
///
427428
/// b. When --graphql.multiple-create.enabled option is not used
428429
/// - In this case, fields related to multiple mutation and multiple create operations will NOT be written to the config file.
429-
///
430+
///
430431
/// </summary>
431432
[DataTestMethod]
432433
[DataRow(DatabaseType.MSSQL, CliBool.True, DisplayName = "Init command with '--graphql.multiple-create.enabled true' for MsSQL database type")]
@@ -453,7 +454,7 @@ public Task VerifyCorrectConfigGenerationWithMultipleMutationOptions(DatabaseTyp
453454

454455
if (databaseType is DatabaseType.CosmosDB_NoSQL)
455456
{
456-
// A schema file is added since its mandatory for CosmosDB_NoSQL
457+
// A schema file is added since its mandatory for CosmosDB_NoSQL
457458
((MockFileSystem)_fileSystem!).AddFile(TEST_SCHEMA_FILE, new MockFileData(""));
458459

459460
options = new(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
DataSource: {
3+
DatabaseType: MSSQL,
4+
Options: {
5+
set-session-context: false
6+
}
7+
},
8+
Runtime: {
9+
Rest: {
10+
Enabled: true,
11+
Path: /api,
12+
RequestBodyStrict: true
13+
},
14+
GraphQL: {
15+
Enabled: true,
16+
Path: /graphql,
17+
AllowIntrospection: true
18+
},
19+
Host: {
20+
Cors: {
21+
AllowCredentials: false
22+
},
23+
Authentication: {
24+
Provider: EntraID,
25+
Jwt: {
26+
Audience: aud-xxx,
27+
Issuer: issuer-xxx
28+
}
29+
},
30+
Mode: Production
31+
}
32+
},
33+
Entities: []
34+
}

src/Cli.Tests/TestHelper.cs

+26
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,32 @@ public static Process ExecuteDabCommand(string command, string flags)
175175
}
176176
}";
177177

178+
/// <summary>
179+
/// Only Runtime section containing both rest and graphql enabled. The authentication provider can be replaced with <>.
180+
/// </summary>
181+
public const string RUNTIME_SECTION_JWT_AUTHENTICATION_PLACEHOLDER = @"
182+
""runtime"": {
183+
""rest"": {
184+
""path"": ""/api"",
185+
""enabled"": true
186+
},
187+
""graphql"": {
188+
""path"": ""/graphql"",
189+
""enabled"": true,
190+
""allow-introspection"": true
191+
},
192+
""host"": {
193+
""mode"": ""development"",
194+
""cors"": {
195+
""origins"": [],
196+
""allow-credentials"": false
197+
},
198+
""authentication"": {
199+
""provider"": ""<>""
200+
}
201+
}
202+
}";
203+
178204
/// <summary>
179205
/// Configuration with unresolved environment variable references on
180206
/// properties of various data types (string, enum, bool, int).

src/Cli.Tests/UtilsTests.cs

+4
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ public void TestApiPathIsWellFormed(string apiPath, bool expectSuccess)
207207
[DataRow("AzureAD", null, "issuer-xxx", false, DisplayName = "FAIL: AzureAD incorrectly configured with no audience specified.")]
208208
[DataRow("AzureAD", "aud-xxx", null, false, DisplayName = "FAIL: AzureAD incorrectly configured with no issuer specified.")]
209209
[DataRow("AzureAD", null, null, false, DisplayName = "FAIL: AzureAD incorrectly configured with no audience or issuer specified.")]
210+
[DataRow("EntraID", "aud-xxx", "issuer-xxx", true, DisplayName = "PASS: EntraID correctly configured with both audience and issuer.")]
211+
[DataRow("EntraID", null, "issuer-xxx", false, DisplayName = "FAIL: EntraID incorrectly configured with no audience specified.")]
212+
[DataRow("EntraID", "aud-xxx", null, false, DisplayName = "FAIL: EntraID incorrectly configured with no issuer specified.")]
213+
[DataRow("EntraID", null, null, false, DisplayName = "FAIL: EntraID incorrectly configured with no audience or issuer specified.")]
210214
public void TestValidateAudienceAndIssuerForAuthenticationProvider(
211215
string authenticationProvider,
212216
string? audience,

src/Cli.Tests/ValidateConfigTests.cs

+26
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,32 @@ public void TestValidateConfigFailsWithInvalidGraphQLDepthLimit(object? depthLim
145145
}
146146
}
147147

148+
/// <summary>
149+
/// This Test is used to verify that DAB fails when the JWT properties are missing for OAuth based providers
150+
/// </summary>
151+
[DataTestMethod]
152+
[DataRow("AzureAD")]
153+
[DataRow("EntraID")]
154+
public void TestMissingJwtProperties(string authScheme)
155+
{
156+
string ConfigWithJwtAuthentication = $"{{{SAMPLE_SCHEMA_DATA_SOURCE}, {RUNTIME_SECTION_JWT_AUTHENTICATION_PLACEHOLDER}, \"entities\": {{ }}}}";
157+
ConfigWithJwtAuthentication = ConfigWithJwtAuthentication.Replace("<>", authScheme, StringComparison.OrdinalIgnoreCase);
158+
159+
// create an empty config file
160+
((MockFileSystem)_fileSystem!).AddFile(TEST_RUNTIME_CONFIG_FILE, ConfigWithJwtAuthentication);
161+
162+
ValidateOptions validateOptions = new(TEST_RUNTIME_CONFIG_FILE);
163+
164+
try
165+
{
166+
Assert.IsFalse(ConfigGenerator.IsConfigValid(validateOptions, _runtimeConfigLoader!, _fileSystem!));
167+
}
168+
catch (Exception ex)
169+
{
170+
Assert.Fail($"Unexpected Exception thrown: {ex.Message}");
171+
}
172+
}
173+
148174
/// <summary>
149175
/// This Test is used to verify that the validate command is able to catch when data source field or entities field is missing.
150176
/// </summary>

src/Core/AuthenticationHelpers/EasyAuthAuthenticationHandler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ protected override Task<AuthenticateResult> HandleAuthenticateAsync()
9292
if (claimsPrincipal is not null)
9393
{
9494
// AuthenticationTicket is Asp.Net Core Abstraction of Authentication information
95-
// Ref: aspnetcore/src/Http/Authentication.Abstractions/src/AuthenticationTicket.cs
95+
// Ref: aspnetcore/src/Http/Authentication.Abstractions/src/AuthenticationTicket.cs
9696
AuthenticationTicket ticket = new(claimsPrincipal, EasyAuthAuthenticationDefaults.AUTHENTICATIONSCHEME);
9797
AuthenticateResult success = AuthenticateResult.Success(ticket);
9898
return Task.FromResult(success);

src/Core/AuthenticationHelpers/SupportedAuthNProviders.cs

+3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ namespace Azure.DataApiBuilder.Core.AuthenticationHelpers;
66
internal static class SupportedAuthNProviders
77
{
88
public const string APP_SERVICE = "AppService";
9+
910
public const string AZURE_AD = "AzureAD";
1011
public const string ENTRA_ID = "EntraID";
12+
1113
public const string GENERIC_OAUTH = "Custom";
1214
public const string SIMULATOR = "Simulator";
15+
1316
public const string STATIC_WEB_APPS = "StaticWebApps";
1417
}

src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs

+11-7
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,16 @@ public void ValidateEasyAuthConfig()
5959
}
6060
}
6161

62-
[TestMethod("AuthN validation passes when all values are provided when provider not EasyAuth")]
63-
public void ValidateJwtConfigParamsSet()
62+
[DataTestMethod("AuthN validation passes when all values are provided when provider not EasyAuth")]
63+
[DataRow("AzureAD")]
64+
[DataRow("EntraID")]
65+
public void ValidateJwtConfigParamsSet(string authenticationProvider)
6466
{
6567
JwtOptions jwt = new(
6668
Audience: "12345",
6769
Issuer: "https://login.microsoftonline.com/common");
6870
AuthenticationOptions authNConfig = new(
69-
Provider: "AzureAD",
71+
Provider: authenticationProvider,
7072
Jwt: jwt);
7173
RuntimeConfig config = CreateRuntimeConfigWithOptionalAuthN(authNConfig);
7274

@@ -108,14 +110,16 @@ public void ValidateAuthNSectionNotNecessary()
108110
}
109111
}
110112

111-
[TestMethod("AuthN validation fails when either Issuer or Audience not provided not EasyAuth")]
112-
public void ValidateFailureWithIncompleteJwtConfig()
113+
[DataTestMethod("AuthN validation fails when either Issuer or Audience not provided not EasyAuth")]
114+
[DataRow("AzureAD")]
115+
[DataRow("EntraID")]
116+
public void ValidateFailureWithIncompleteJwtConfig(string authenticationProvider)
113117
{
114118
JwtOptions jwt = new(
115119
Audience: "12345",
116120
Issuer: string.Empty);
117121
AuthenticationOptions authNConfig = new(
118-
Provider: "AzureAD",
122+
Provider: authenticationProvider,
119123
Jwt: jwt);
120124

121125
RuntimeConfig config = CreateRuntimeConfigWithOptionalAuthN(authNConfig);
@@ -136,7 +140,7 @@ public void ValidateFailureWithIncompleteJwtConfig()
136140
Audience: string.Empty,
137141
Issuer: DEFAULT_ISSUER);
138142
authNConfig = new(
139-
Provider: "AzureAD",
143+
Provider: authenticationProvider,
140144
Jwt: jwt);
141145
config = CreateRuntimeConfigWithOptionalAuthN(authNConfig);
142146

src/Service.Tests/Configuration/ConfigurationTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ public async Task TestValidateConfigForValidDepthLimit(int? depthLimit)
14021402

14031403
/// <summary>
14041404
/// This method validates that depth-limit outside the valid range should fail validation
1405-
/// during `dab validate` and `dab start`.
1405+
/// during `dab validate` and `dab start`.
14061406
/// </summary>
14071407
/// <param name="depthLimit"></param>
14081408
/// <param name="expectedSuccess"></param>
@@ -4396,7 +4396,7 @@ public async Task ValidateNextLinkUsage()
43964396

43974397
/// <summary>
43984398
/// Tests the enforcement of depth limit restrictions on GraphQL queries and mutations in non-hosted mode.
4399-
/// Verifies that requests exceeding the specified depth limit result in a BadRequest,
4399+
/// Verifies that requests exceeding the specified depth limit result in a BadRequest,
44004400
/// while requests within the limit succeed with the expected status code.
44014401
/// Also verifies that the error message contains the current and allowed max depth limit value.
44024402
/// Example:

0 commit comments

Comments
 (0)