I have an application that is authenticating users against Azure Active Directory. The returned JWT token is then passed from the application into a Web API that validates the token.
I then ask Active Directory to generate another JWT token on behalf of the user for SQL Azure. The Web API can now authenticate to SQL Azure with the OnBehalfOf token. From here the database is implementing RLS (Row Level Security) by using some unique information in the JWT to filter the results accordingly.
For this to work, the Active Directory application used to request the onBehalfOf token must have requiredResourceAccess for SQL Azure. This is done by editing the application manifest in the Azure portal specifying that SQL Azure (022907d3-0f1b-48f7-badc-1ba6abab6d66) can Access Azure SQL DB and Data Warehouse (c39ef2d1-04ce-46dc-8b5f-e9a5c60f0fc9).
"requiredResourceAccess": [
{
"resourceAppId": "022907d3-0f1b-48f7-badc-1ba6abab6d66",
"resourceAccess": [
{
"id": "c39ef2d1-04ce-46dc-8b5f-e9a5c60f0fc9",
"type": "Scope"
}
]
}
]
I want to support social logins and Azure B2C is generally a better fit for my requirements. But is it possible for Azure Active Directory B2C to support this authentication flow?
const string tenant = "...";
const string clientId = "...";
const string clientSecret = "...";
const string connectionString = "Server=...database.windows.net,1433;Initial Catalog=...;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False";
async Task Main()
{
try
{
var authenticationContext = new AuthenticationContext(TenantSettings.Authority);
var result = await authenticationContext.AcquireTokenAsync(
"https://database.windows.net/",
new ClientCredential(clientId, clientSecret),
new UserAssertion("eyJ...")).ConfigureAwait(false);
await ConnectToDatabaseAsync(result.AccessToken.Dump());
}
catch (Exception ex)
{
$"Failed to connect to Azure SQL.\n\tReason: {ex.Message}".Dump();
}
}
private static async Task ConnectToDatabaseAsync(string accessToken)
{
using (var connection = new SqlConnection(connectionString))
{
connection.AccessToken = accessToken;
await connection.OpenAsync().ConfigureAwait(false);
using (var command = new SqlCommand("select USER_NAME()", connection))
using (var reader = await command.ExecuteReaderAsync())
{
await reader.ReadAsync().ConfigureAwait(false);
reader.GetString(0).Dump("User");
}
}
}
private static class TenantSettings
{
public const string Authority = Instance + Tenant;
public const string Instance = "https://login.microsoftonline.com/";
public const string Tenant = tenant;
}