Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/Core/Resolvers/MsSqlQueryExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ public override string GetSessionParamsQuery(HttpContext? httpContext, IDictiona

// Counter to generate different param name for each of the sessionParam.
IncrementingInteger counter = new();
const string SESSION_KEY_NAME = $"{BaseQueryStructure.PARAM_NAME_PREFIX}session_key";
const string SESSION_PARAM_NAME = $"{BaseQueryStructure.PARAM_NAME_PREFIX}session_param";
StringBuilder sessionMapQuery = new();

Expand All @@ -528,10 +529,12 @@ public override string GetSessionParamsQuery(HttpContext? httpContext, IDictiona

foreach ((string claimType, string claimValue) in sessionParams)
{
string keyName = $"{SESSION_KEY_NAME}{counter.Current()}";
string paramName = $"{SESSION_PARAM_NAME}{counter.Next()}";
parameters.Add(keyName, new(claimType));
parameters.Add(paramName, new(claimValue));
// Append statement to set read only param value - can be set only once for a connection.
Comment on lines +532 to 536
string statementToSetReadOnlyParam = "EXEC sp_set_session_context " + $"'{claimType}', " + paramName + ", @read_only = 0;";
string statementToSetReadOnlyParam = "EXEC sp_set_session_context " + keyName + ", " + paramName + ", @read_only = 0;";
sessionMapQuery = sessionMapQuery.Append(statementToSetReadOnlyParam);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// Licensed under the MIT License.

#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Azure.DataApiBuilder.Config.ObjectModel;
Expand Down Expand Up @@ -325,7 +327,6 @@ public async Task TestValidStaticWebAppsEasyAuthTokenWithAnonymousRoleOnly()
DisplayName = "Anonymous role - X-MS-API-ROLE is not honored")]
[DataRow(true, "author",
DisplayName = "Authenticated role - existing X-MS-API-ROLE is honored")]
[TestMethod]
public async Task TestClientRoleHeaderPresence(bool addAuthenticated, string clientRoleHeader)
{
string generatedToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(addAuthenticated);
Expand All @@ -344,6 +345,46 @@ await SendRequestAndGetHttpContextState(
ignoreCase: true);
}

/// <summary>
/// Tests we ensure that an invalid query in the EasyAuth header does not result in a successful request.
/// </summary>
[TestMethod]
public async Task TestInvalidQueryInHeader()
{
string header = @"
{
""auth_typ"":""aad"",
""claims"":[
{
""typ"":""x', N'v';SET IDENTITY_INSERT authors ON;INSERT INTO authors (id, name, birthdate) VALUES (10001, 'Hidden Author', '2001-01-01');SET IDENTITY_INSERT authors OFF;SELECT 1 AS inserted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;--"",
""val"":""x""
}
],
""UserRoles"":[""anonymous""]
}";

string generatedToken = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(header));
HttpContext postMiddlewareContext =
await SendRequestAndGetHttpContextState(
generatedToken,
EasyAuthType.StaticWebApps,
clientRoleHeader: "anonymous");
Assert.AreEqual(expected: (int)HttpStatusCode.OK, actual: postMiddlewareContext.Response.StatusCode);

using IHost host = await WebHostBuilderHelper.CreateWebHost(EasyAuthType.StaticWebApps.ToString(), false);
TestServer server = host.GetTestServer();
HttpClient client = server.CreateClient();

HttpRequestMessage request = new(HttpMethod.Get, $"api/Author/id/10001");
HttpResponseMessage response = await client.SendAsync(request);
string responseBody = await response.Content.ReadAsStringAsync();
Comment on lines +348 to +380

Assert.IsFalse(responseBody.Contains($"\"id\":10001"),
"The GET request should not return the invalid row.");
Assert.IsFalse(responseBody.Contains("Hidden Author"),
"The GET request should not return any information related to the invalid row.");
}

/// <summary>
/// - Ensures an invalid EasyAuth header payload results in HTTP 401 Unauthorized response
/// A correctly configured EasyAuth environment guarantees an EasyAuth payload for authenticated requests.
Expand Down
Loading