30
loading...
This website collects cookies to deliver better user experience
appsettings.json
and add the following settings:"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "<your client id>",
"Domain": "<your tenant name>.onmicrosoft.com",
"TenantId": "<your tenant id>"
},
dotnet add package microsoft.identity.web
startup.cs
and update the ConfigureServices()
method with the following code:var ScopeClaim = "http://schemas.microsoft.com/identity/claims/scope";
var ExpectedRole = "access_as_application";
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.AddAuthorization(options => options.AddPolicy(
"AllowedAccess",
policyBuilder => policyBuilder.RequireAssertion(
context
=> context.User.IsInRole(ExpectedRole)
|| context.User.HasClaim(ScopeClaim,"access_as_user"))
));
services.AddControllers();
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
});
Configure()
method, ensure you add app.UseAuthentication()
before the UseAuthorization() callWeatherForecastController.cs
and add the following action:[HttpGet]
[Authorize(Policy="AllowedAccess")]
public async Task<string> Get(string city)
{
var context = this.HttpContext;
var url = $"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={configuration["WeatherApiKey"]}";
var client = new HttpClient();
var response = await client.GetStringAsync(url);
return response;
}
appsettings.json
(a big No-No as this is the least secure options)az login
az group create --name "<your-resource-group-name>" -l "<desired region>"
az keyvault create --name "<your-unique-keyvault-name>" --resource-group "<your-resource-group-name>" --location "<desired region>"
az ad sp create-for-rbac --role Reader --scopes <your Key Vault Resource Id>
az login --service-principal -u http://<your SP Name> -p <your SP password> --tenant <your Tenant Id>
az keyvault set-policy -n <your KV name> --secret-permissions get list --object-id <your SP **app id**>
NOTE: the docs say that you need to use the object id
of the service principal, but I was unable to get it working. it worked as soon as I changed the command to use the **App ID(( of the service principal
You'll need to run this command as an Azure Contributor/Owner
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
Program.cs
and update the CreateHostBuilder()
method with the following code:public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();
config.AddAzureKeyVault( new Uri("https://cm-identity-kv.vault.azure.net"),
//new DefaultAzureCredential());
new ChainedTokenCredential(
new AzureCliCredential(),
new ManagedIdentityCredential()
));
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseUrls("http://localhost:8080");
});
appsettings.json
and try to map them to Azure Key Vault secrets. This means that we need to add an empy setting in our code. Open appsettings.json
and add this: "WeatherApiKey": ""
Configuration
object. requirements.txt
file and add the following dependencies:msal>=1.12.0
requests>=2.25.1
azure-identity>=1.6.0
azure-keyvault-secrets>=4.3.0
config.json
. Add the following code and populate it with the values you got from running Client App registration using the .NET Notebook.{
"authority": "https://login.microsoftonline.com/<your tenant id>",
"client_id": "<your client id>",
"scope": ["api://855dac46-661b-4463-97cf-d57a190bf2ed/.default"],
"vault_url": "https://<your vault name>.vault.azure.net"
}
Notice the scope
here. We are using the App Role configured in our App Registration but instead using the value as is, we replace the actual role name with .default
. This is necessary since we are using the Client Credential flow and, therefore, there is no way to consent to permissions. You can read all about .default
here.
console.py
file and add the following code:import json
import requests
import msal
from azure.identity import ChainedTokenCredential, AzureCliCredential, ManagedIdentityCredential
from azure.keyvault.secrets import SecretClient
jsondata = open("config.json","r")
config = json.load(jsondata)
credential = ChainedTokenCredential(AzureCliCredential(),ManagedIdentityCredential())
secret_client = SecretClient(config["vault_url"], credential=credential)
aad_client_secret = secret_client.get_secret("AadClientSecret")
app = msal.ConfidentialClientApplication(
client_id=config["client_id"],
client_credential=aad_client_secret.value,
authority=config["authority"],
)
result = None
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
result = app.acquire_token_for_client(scopes=config["scope"])
if "error" in result:
print(result["error_description"])
if "access_token" in result:
session = requests.sessions.Session()
session.headers.update({'Authorization': f'Bearer {result["access_token"]}'})
response = session.get("http://localhost:8080/weatherforecast?city=London")
if response.status_code == 200 :
print(response.content)
else:
print(f'Request failed. Response code: {response.status_code}, reason: {response.reason}')
dotnet run
. Then set up the Python console app and run it. Be aware that the instructions for setting up the virtual environment are different across OS'es. On Windows, open a console and type:py -m venv .venv
.venv/scripts/activate
pip install -r requirements.txt
py console.exe
/.default
scope due to the fact that that there is no user to interactively consent to the required permissions. Finally, since we made use of the Client Credential flow, we added Azure Key Vault to secure sensitive information.