A library which includes a dotnet Basic Authentication middleware component which can be added to dotnet web and API apps on Azure to enable classic/old RFC 2617 Basic Authentication. Please note, Basic Auth is one of the oldest forms of web authentication and is not known for being the most secure. Use and implement at your own risk and only over HTTPS/TLS to prevent sending user names and passwords unencrypted over the Internet.
- See CHANGELOG.md for review history and recorded security findings.
- Use HTTPS/TLS only. This middleware rejects non-HTTPS requests.
- Do not store credentials directly in source code.
- Add host-level rate limiting and monitoring for internet-facing workloads.
- Prefer modern auth (OIDC/OAuth/JWT) for public-facing production apps where possible.
Install - Leveraging NuGet Package
Assuming you would like to add the library to your project via a NuGet package, the following are the steps required:
- Have an existing
dotnet webappordotnet apiappcreated (if starting from scratch, simply typedotnet new webapp --name "myWebApp"to create a new one). - From the command line change the directory the the directory with a
.csprojfile in it (cd myWebAppin the example above). - Add the package to your project by typing
dotnet add package joelbyford.BasicAuth. - Modify your code startup code as appropriate (see later in this readme).
If you would rather use the raw source code, just copy the BasicAuth.cs file into your existing project instead.
Once installed, to use the library, simply modify the Configure method in your startup.cs to call the library in any one of two ways:
For simple use cases, this may satisfy your need. Source credentials from environment variables or a secret store.
using joelbyford;
using System;
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
string basicAuthRealm = "mywebsite.com";
string basicAuthUser = Environment.GetEnvironmentVariable("BASIC_AUTH_USER");
string basicAuthPass = Environment.GetEnvironmentVariable("BASIC_AUTH_PASS");
app.UseMiddleware<joelbyford.BasicAuth>(basicAuthRealm, basicAuthUser, basicAuthPass);
}
If you would like to control how and where you get the users and passwords from, this method is best (e.g. you are obtaining from a database or secure configuration source).
using joelbyford;
using System.IO;
using System.Collections.Generic;
using System.Text.Json;
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
Dictionary<string, string> myUsers = new Dictionary<string, string>();
var packageJson = File.ReadAllText("authorizedUsers.secure.json");
myUsers = JsonSerializer.Deserialize<Dictionary<string, string>>(packageJson);
string basicAuthRealm = "mywebsite.com";
app.UseMiddleware<joelbyford.BasicAuth>(basicAuthRealm, myUsers);
}
In this example, credentials are loaded from a controlled configuration source. Avoid committing credential files to source control and rotate passwords regularly.
If you must use a local file for development, do not store production credentials in that file and exclude it from git.
Example format:
{
"testUser" : "testPassword",
"devUser" : "devPassword"
}
This can of course be loaded in from a database call instead as long as users and passwords are loaded into a Dictionary<string, string>
To see an example of this in use, please see startup.cs in the https://github.com/joelbyford/CSVtoJSONcore repo.
To quickly verify middleware behavior (including a bogus endpoint auth check), a runnable sample is included at harness/BasicAuthHarness.
Run the harness:
dotnet run --project harness/BasicAuthHarness/BasicAuthHarness.csproj
In a second terminal, run the included curl test script:
powershell -ExecutionPolicy Bypass -File .\harness\BasicAuthHarness\testing\test-auth.ps1
Both scripts validate the same 4 assertions:
- Missing Authorization header ->
401 - Invalid credentials ->
401 - Valid credentials to
POST /bogus->404 - Valid credentials to
GET /health->200
Each script prints PASS/FAIL for every assertion, then prints:
trueif all assertions pass (process exit code0)falseif any assertion fails (process exit code1)
PowerShell usage:
powershell -ExecutionPolicy Bypass -File .\harness\BasicAuthHarness\testing\test-auth.ps1
powershell -ExecutionPolicy Bypass -File .\harness\BasicAuthHarness\testing\test-auth.ps1 "http://localhost:5057" "demoUser" "demoPass!123"
Bash usage:
bash harness/BasicAuthHarness/testing/test-auth.sh
bash harness/BasicAuthHarness/testing/test-auth.sh http://localhost:5057 demoUser demoPass!123
Parameter order for both scripts:
BaseUrlUserPass
Alternatively you may call the tests via the REST Client VSCode plugin in the testing.http file.
Expected results:
- Missing Authorization header ->
401 Unauthorized - Invalid credentials ->
401 Unauthorized - Valid credentials to
POST /bogus->404 Not Found(auth passed, route missing) - Valid credentials to
GET /health->200 OK
Note: The harness runs on HTTP for convenience and uses X-Forwarded-Proto: https in curl commands to simulate TLS termination at a reverse proxy.
If you use GitHub branch protection for main, require the status check from this workflow:
- Workflow:
PR Harness Bash Test - Job/check name:
harness-bash-test
In GitHub, go to Settings -> Branches -> Branch protection rules for main and add this check under Require status checks to pass before merging.
PLEASE NOTE this library allows the developer to use X-Forwarded-Proto: https in the API calls to ease development and testing in environments (like local workstations) that do not have SSL certificates installed. Do NOT use this in production as it will expose passwords in clear text without a secure SSL socket.