I have to admit, this was a weird and tough one. All I wanted to do was run an ASP.NET Razor Pages app inside a container using Https and Azure Active Directory authentication. Well, this was definitely a fun one to solve. In this blog post I'll show you exactly how to do the following:
- export the .NET Dev certs to use with Docker
- configure the Azure AD authentication
- configure the SameSite cookie policy in .NET
- configure Docker to use the dev-certs
Export the .NET Dev certs
In order to be able to work in local dev with Docker and HTTPS we need a certificate. And the easiest way to get a cert is to use the .NET dev certs - they are free and available.
Note: this should only be used for local Dev to unblock certain scenarios
Open your favorite terminal and type the following
dotnet dev-certs https --clean
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p <your secret>
### If you're using PowerShell, then you have to use the following command instead
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\aspnetapp.pfx -p <your secret>
dotnet dev-certs https --trust
Configure the ASP.NET Core Web App
By default, ASP.NET Core website have HSTS and HTTPS redirection enabled. This means that when running the application, it will expect and redirect all requests to the TLS-enabled port. I like to set mine to the standard 5001
since .NET 6 and 7 are now randomizing the app ports. You can change the default ports in the Properties\launchSettings.json
file. This is what mine looks like:
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:43362",
"sslPort": 44382
}
},
"profiles": {
"AzureADAuthInDocker": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5000;https://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Implement the necessary authentication, you need to add the following NuGet packages:
- Microsoft.Identity.Web
- Microsoft.Identity.Web.UI
In the appsettings.json
file add the following AzureAD specific settings:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "<your Azure AD tenant name>.onmicrosoft.com",
"TenantId": "<your Azure AD tenant ID>",
"ClientId": "<your Azure AD App Registration client ID>",
"CallbackPath": "/signin-oidc"
},
Update the program.cs
add the following code:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
// code ommitted
app.UseAuthentication();
app.UseAuthorization();
At this point you can run the application locally using dotnet run
and if everything has been configured correctly, you should be prompted to authenticate with your organizational (Azure AD) account
Create a Cookie Policy
If you plan on using Cookies in your solution, then you need to add a cookie policy. In Program.cs
above the authentication settings, add the following code:
builder.Services.Configure<CookiePolicyOptions>(
options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.Secure = CookieSecurePolicy.Always;
});
Then, just above the app.UseAuthentication()
you need to add this:
app.UseCookiePolicy();
Run the application and test that everything's working as expected!
If you get a cookie error as per below, make sure you have the right settings. Check everything and try again:
Configure Docker for our web app
There are some prerequisites when it comes to working with Docker, namely that you need to have Docker Desktop installed and WSL2 enabled if you want to use Linux containers. Make sure to have these installed correctly.
When it comes to creating the Docker files, I like to lean on VS Code to do the heavy lifting for me. You can find the information on how to set things up for your ASP.NET app here
Running the appropriate Docker commands from the VS Code pallette, should generate the following 3 files:
- Dockerfile
- docker-compose.yml
- docker-compose.debug.yml
I left my Dockerfile
mostly unchanged apart from the ENV ASPNETCORE_URLs value which I updated to: http://+:5000;https://+:5001
My docker-compose.yml
file looks like this:
version: '3.4'
services:
azureadauthindocker:
image: azureadauthindocker
build:
context: .
dockerfile: ./Dockerfile
ports:
- 5000:5000
And finally, the bulk of the changes took place in the docker-compose.debug.yml
# Please refer https://aka.ms/HTTPSinContainer on how to setup an https developer certificate for your ASP .NET Core service.
version: '3.4'
services:
azureadauthindocker:
image: azureadauthindocker
build:
context: .
dockerfile: ./Dockerfile
ports:
- 5000:5000
- 5001:5001
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:5001;http://+:5000
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
- ASPNETCORE_Kestrel__Certificates__Default__Password=<your secret>
volumes:
- ~/.vsdbg:/remote_debugger:rw
- C:\Users\chmatsk\.aspnet\https:/https/:ro
With these changes, I can run my web app inside Docker directly from VS Code.
And this is an example with everything working end-to-end
If you want to run the container from the command line, then this is the command you need to use
docker run --rm -it -p 5000:5000 -p 5001:5001 -e ASPNETCORE_URLS="https://+:5001;http://+:5000" -e ASPNETCORE_HTTPS_PORT=5001 -e ASPNETCORE_Kestrel__Certificates__Default__Password="<your secret>" -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx -v C:\Users\chmatsk\.aspnet\https:/https/ <your image>
Running this command should produce the following output and your website should be accessible on https://localhost:5001
Reach out if you have any questions!
Top comments (3)
Hello, I have a question, I have configured my azure connection but the AZUREAD__CALLBACKPATH="/signin-oidc" is done via an http route while the route configured in the azure portal is in https.The problem is that the route is therefore not found and therefore I cannot connect
Do you know how to make this callback switch to https?
Thx for your response
Hello, I have the same problem with the callback in http.
Have you found a solution ?
Is this utilizing a Linux or Windows container?