Search code examples
azureazure-active-directoryazure-keyvaultappsettingsazure-appservice

Access client secret (Azure AD auth) from app settings .net 6 app


I have a .net 6 app using azure ad for authentication. Below are the details:

appsettings.json

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "",
    "ClientId": "",
    "TenantId": "",
    "CallbackPath": "/signin-oidc",
    "SignedOutCallbackPath ": "/signout-oidc"
    "ClientSecret": "@Microsoft.KeyVault(SecretUri=https://mykv.vault.azure.net/secrets/myclientsecret/)"

Program.cs

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                            .AddMicrosoftIdentityWebApp(Configuration)
                            .EnableTokenAcquisitionToCallDownstreamApi()
                            .AddInMemoryTokenCaches()
                            .AddDownstreamApi("MyService", Configuration.GetSection("MyService")); //MyService is also present in appsetting with baseurl and scopes

The app is deployed in app service and has the following app setting: Name: AzureAd__ClientSecret Value: @Microsoft.KeyVault(SecretUri=https://mykv.vault.azure.net/secrets/myclientsecret/)

I expect the ClientSecret value read from keyvault and the rest to be read from the appsettings json. How can I make this happen? If I hardcode client secret in appsetting it works. I am struggling to understand why this is not allowing sign in?

Also RedirectURI has been added.

Snap of App Service Configuration

enter image description here


Solution

  • Iam able to authenticate and login even without the Client Secret.

    I expect the ClientSecret value read from keyvault and the rest to be read from the appsettings json.

    I have set the key ClientSecret without any value in appsettings.json file.

    My appsettings.json:

    {
      "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Domain": "*****.onmicrosoft.com",
        "TenantId": "**********",
        "ClientId": "**********",
        "CallbackPath": "/signin-oidc",
        "ClientSecret": ""
      },
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "KeyVault": {
        "URI": "https://HarshuKV8June.vault.azure.net/"
      }
    }
    

    My .csproj file:

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <UserSecretsId>aspnet-WebApplication2-f96bb6f0-eef0-4193-a9b3-6a006134f076</UserSecretsId>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.16" NoWarn="NU1605" />
        <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.16" NoWarn="NU1605" />
        <PackageReference Include="Microsoft.Identity.Web" Version="2.7.0" />
        <PackageReference Include="Microsoft.Identity.Web.UI" Version="2.7.0" />
      </ItemGroup>
    </Project>
    

    Use the below code to retrieve the Client Secret from Azure Key Vault.

    Use, any one line of below code to retrieve teh secret value from KeyVault.

    var ClientSecret = secretClient.GetSecret("ClientSecret").Value.Value;
    

    OR

    var secretValue = await secretClient.GetSecretAsync("ClientSecret");
    

    My Program.cs file:

    using Azure.Identity;
    using Azure.Security.KeyVault.Secrets;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authentication.OpenIdConnect;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc.Authorization;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Identity.Web;
    using Microsoft.Identity.Web.UI;
    using System.ComponentModel;
    
    var builder = WebApplication.CreateBuilder(args);
    
    
    var KV = builder.Configuration["KeyVault:URI"];
    var cred = new DefaultAzureCredential();
    var secretClient = new SecretClient(new Uri(KV), cred);
    
    var ClientSecret = secretClient.GetSecret("ClientSecret").Value.Value;
    var secretValue = await secretClient.GetSecretAsync("ClientSecret");
    
    //Setting the ClientSecret to the key in `appsettings.json` file
    builder.Configuration["AzureAD:ClientSecret"] = ClientSecret;
    
    //Retrieving the value from `appsettings.json` file
    var setClientSecret = builder.Configuration.GetValue<string>("AzureAD:ClientSecret");
    
    // Add services to the container.
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
    
    builder.Services.AddAuthorization(options =>
    {   
        options.FallbackPolicy = options.DefaultPolicy;
    });
    builder.Services.AddRazorPages()
        .AddMicrosoftIdentityUI();
    
    var app = builder.Build();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");  
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapRazorPages();
    app.MapControllers();
    app.Run();
    
    

    ClientSecret Value from KeyVault:

    enter image description here

    Redirect URI in AAD:

    enter image description here

    Output:

    enter image description here

    Localhost: enter image description here

    Deployed App:

    enter image description here