diff --git a/README.md b/README.md
index 28936f5..30ce7ef 100644
--- a/README.md
+++ b/README.md
@@ -12,5 +12,6 @@ $ git clone https://github.com/redhat-developer/dotnet-bunny && cd dotnet-bunny
### Dependencies
-Dependencies(apk): babeltrace bash bash-completion binutils coreutils file findutils g++ jq libstdc++-dev lldb lttng-ust lttng-tools npm postgresql psqlodbc sed strace unixodbc zlib-dev
-Dependencies(dnf): awk babeltrace bash-completion bc findutils gcc-c++ jq libstdc++-devel lttng-ust lttng-tools npm postgresql-odbc postgresql-server strace unixODBC /usr/bin/file /usr/bin/free /usr/bin/lldb /usr/bin/readelf /usr/bin/su which zlib-devel
+Dependencies(apk): babeltrace bash bash-completion binutils coreutils file findutils g++ jq krb5-server krb5 libstdc++-dev lldb lttng-ust lttng-tools npm postgresql psqlodbc sed strace unixodbc zlib-dev
+Dependencies(apt): krb5-kdc krb5-admin-server krb5-user
+Dependencies(dnf): awk babeltrace bash-completion bc findutils gcc-c++ jq krb5-server krb5-workstation krb5-libs libstdc++-devel lttng-ust lttng-tools npm postgresql-odbc postgresql-server strace unixODBC /usr/bin/file /usr/bin/free /usr/bin/lldb /usr/bin/readelf /usr/bin/su which zlib-devel
diff --git a/kerberos-auth/aspnet-server/Program.cs b/kerberos-auth/aspnet-server/Program.cs
new file mode 100644
index 0000000..fbc70e1
--- /dev/null
+++ b/kerberos-auth/aspnet-server/Program.cs
@@ -0,0 +1,62 @@
+using Microsoft.AspNetCore.Authentication.Negotiate;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Configure Kerberos/Negotiate authentication
+builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
+ .AddNegotiate();
+
+builder.Services.AddAuthorization(options =>
+{
+ options.FallbackPolicy = new AuthorizationPolicyBuilder()
+ .RequireAuthenticatedUser()
+ .Build();
+});
+
+var app = builder.Build();
+
+app.UseAuthentication();
+app.UseAuthorization();
+
+app.MapGet("/", (HttpContext context) =>
+{
+ var user = context.User.Identity;
+ if (user?.IsAuthenticated == true)
+ {
+ Console.WriteLine($"[SERVER] Authenticated user: {user.Name}");
+ return Results.Ok(new
+ {
+ authenticated = true,
+ username = user.Name,
+ authenticationType = user.AuthenticationType,
+ message = "Kerberos authentication successful"
+ });
+ }
+ else
+ {
+ Console.WriteLine("[SERVER] User not authenticated");
+ return Results.Unauthorized();
+ }
+});
+
+// Read configuration from environment
+var port = Environment.GetEnvironmentVariable("SERVER_PORT") ?? "5000";
+var keytabPath = Environment.GetEnvironmentVariable("KRB5_KTNAME");
+
+if (string.IsNullOrEmpty(keytabPath))
+{
+ Console.WriteLine("error: KRB5_KTNAME environment variable not set");
+ Environment.Exit(1);
+}
+
+Console.WriteLine($"[SERVER] Starting on port {port}");
+Console.WriteLine($"[SERVER] Using keytab: {keytabPath}");
+
+app.Urls.Add($"http://localhost:{port}");
+app.Run();
diff --git a/kerberos-auth/aspnet-server/aspnet-server.csproj b/kerberos-auth/aspnet-server/aspnet-server.csproj
new file mode 100644
index 0000000..50f472d
--- /dev/null
+++ b/kerberos-auth/aspnet-server/aspnet-server.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ $(TestTargetFramework)
+
+
+
+
+
+
+
+
+
diff --git a/kerberos-auth/client/Program.cs b/kerberos-auth/client/Program.cs
new file mode 100644
index 0000000..ee9f15e
--- /dev/null
+++ b/kerberos-auth/client/Program.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Text.Json;
+
+// Read configuration from environment
+var serverUrl = Environment.GetEnvironmentVariable("SERVER_URL");
+if (string.IsNullOrEmpty(serverUrl))
+{
+ Console.WriteLine("error: SERVER_URL environment variable not set");
+ Environment.Exit(1);
+ return;
+}
+
+Console.WriteLine($"[CLIENT] Connecting to: {serverUrl}");
+
+// Create HttpClient with default credentials (uses Kerberos)
+var handler = new HttpClientHandler
+{
+ UseDefaultCredentials = true,
+ Credentials = CredentialCache.DefaultCredentials
+};
+
+using var client = new HttpClient(handler);
+
+try
+{
+ var response = await client.GetAsync(serverUrl);
+
+ Console.WriteLine($"[CLIENT] Response status: {response.StatusCode}");
+
+ if (response.IsSuccessStatusCode)
+ {
+ var content = await response.Content.ReadAsStringAsync();
+ Console.WriteLine($"[CLIENT] Response: {content}");
+
+ // Parse JSON to verify authentication
+ var jsonDoc = JsonDocument.Parse(content);
+ if (jsonDoc.RootElement.TryGetProperty("authenticated", out var authProp) &&
+ authProp.GetBoolean())
+ {
+ Console.WriteLine("[CLIENT] SUCCESS: Kerberos authentication verified");
+ Environment.Exit(0);
+ }
+ else
+ {
+ Console.WriteLine("[CLIENT] FAIL: Response does not indicate authentication");
+ Environment.Exit(1);
+ }
+ }
+ else
+ {
+ Console.WriteLine($"[CLIENT] FAIL: HTTP {response.StatusCode}");
+ var content = await response.Content.ReadAsStringAsync();
+ Console.WriteLine($"[CLIENT] Response body: {content}");
+ Environment.Exit(1);
+ }
+}
+catch (Exception ex)
+{
+ Console.WriteLine($"[CLIENT] error: {ex.Message}");
+ Console.WriteLine($"[CLIENT] Stack trace: {ex.StackTrace}");
+ Environment.Exit(1);
+}
diff --git a/kerberos-auth/client/client.csproj b/kerberos-auth/client/client.csproj
new file mode 100644
index 0000000..4227b29
--- /dev/null
+++ b/kerberos-auth/client/client.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ $(TestTargetFramework)
+
+
+
diff --git a/kerberos-auth/setup-kdc.sh b/kerberos-auth/setup-kdc.sh
new file mode 100755
index 0000000..44d1e09
--- /dev/null
+++ b/kerberos-auth/setup-kdc.sh
@@ -0,0 +1,134 @@
+#!/usr/bin/env bash
+
+# Setup a local MIT Kerberos KDC for testing
+# This script creates an ephemeral, isolated Kerberos environment
+
+set -euo pipefail
+
+# Check for required Kerberos tools
+if ! command -v kdb5_util &> /dev/null; then
+ echo "error: kdb5_util not found. Please install Kerberos server packages."
+ exit 1
+fi
+
+if ! command -v krb5kdc &> /dev/null; then
+ echo "error: krb5kdc not found. Please install Kerberos server packages."
+ exit 1
+fi
+
+if ! command -v kadmin.local &> /dev/null; then
+ echo "error: kadmin.local not found. Please install Kerberos admin packages."
+ exit 1
+fi
+
+# Environment setup
+export TEST_DIR="${1:-}"
+if [[ -z "${TEST_DIR}" ]]; then
+ echo "error: TEST_DIR not provided"
+ exit 1
+fi
+
+export REALM="${2:-}"
+if [[ -z "${REALM}" ]]; then
+ echo "error: REALM not provided"
+ exit 1
+fi
+
+export KDC_PORT="${3:-}"
+if [[ -z "${KDC_PORT}" ]]; then
+ echo "error: KDC_PORT not provided"
+ exit 1
+fi
+
+export KRB5_CONFIG="${TEST_DIR}/krb5.conf"
+export KRB5_KDC_PROFILE="${TEST_DIR}/kdc.conf"
+
+echo "Setting up KDC in ${TEST_DIR}"
+echo "Realm: ${REALM}"
+echo "KDC Port: ${KDC_PORT}"
+
+# Create krb5.conf
+cat > "${KRB5_CONFIG}" << EOF
+[libdefaults]
+ default_realm = ${REALM}
+ dns_lookup_realm = false
+ dns_lookup_kdc = false
+ ticket_lifetime = 24h
+ renew_lifetime = 7d
+ forwardable = true
+ rdns = false
+ default_ccache_name = FILE:${TEST_DIR}/krb5cc
+
+[realms]
+ ${REALM} = {
+ kdc = localhost:${KDC_PORT}
+ admin_server = localhost:${KDC_PORT}
+ default_domain = localhost
+ }
+
+[domain_realm]
+ .localhost = ${REALM}
+ localhost = ${REALM}
+EOF
+
+# Create kdc.conf
+cat > "${KRB5_KDC_PROFILE}" << EOF
+[kdcdefaults]
+ kdc_ports = ${KDC_PORT}
+ kdc_tcp_ports = ${KDC_PORT}
+
+[realms]
+ ${REALM} = {
+ database_name = ${TEST_DIR}/principal
+ admin_keytab = FILE:${TEST_DIR}/kadm5.keytab
+ acl_file = ${TEST_DIR}/kadm5.acl
+ key_stash_file = ${TEST_DIR}/.k5.${REALM}
+ max_life = 10h 0m 0s
+ max_renewable_life = 7d 0h 0m 0s
+ master_key_type = aes256-cts
+ supported_enctypes = aes256-cts:normal aes128-cts:normal
+ default_principal_flags = +preauth
+ }
+EOF
+
+# Create ACL file for kadmin
+echo "*/admin@${REALM} *" > "${TEST_DIR}/kadm5.acl"
+
+# Initialize KDC database
+echo "Initializing KDC database..."
+kdb5_util create -s -P masterpassword -r "${REALM}" -d "${TEST_DIR}/principal" 2>&1 | grep -v "^Loading" || true
+
+# Start KDC
+echo "Starting KDC..."
+krb5kdc -n &
+KDC_PID=$!
+echo "${KDC_PID}" > "${TEST_DIR}/kdc.pid"
+
+# Wait for KDC to be ready
+sleep 2
+
+# Verify KDC is running
+if ! ps -p "${KDC_PID}" > /dev/null 2>&1; then
+ echo "error: KDC failed to start"
+ exit 1
+fi
+
+echo "KDC started successfully (PID: ${KDC_PID})"
+
+# Create principals
+echo "Creating principals..."
+kadmin.local -r "${REALM}" -q "addprinc -randkey HTTP/localhost@${REALM}" 2>&1 | grep -v "^Authenticating" || true
+kadmin.local -r "${REALM}" -q "addprinc -pw clientpassword testclient@${REALM}" 2>&1 | grep -v "^Authenticating" || true
+
+# Export keytabs
+echo "Exporting keytabs..."
+kadmin.local -r "${REALM}" -q "ktadd -k ${TEST_DIR}/http.keytab HTTP/localhost@${REALM}" 2>&1 | grep -v "^Authenticating" || true
+kadmin.local -r "${REALM}" -q "ktadd -k ${TEST_DIR}/client.keytab testclient@${REALM}" 2>&1 | grep -v "^Authenticating" || true
+
+# Set proper permissions
+chmod 600 "${TEST_DIR}"/*.keytab
+
+echo "KDC setup complete!"
+echo "KRB5_CONFIG=${KRB5_CONFIG}"
+echo "Service keytab: ${TEST_DIR}/http.keytab"
+echo "Client keytab: ${TEST_DIR}/client.keytab"
diff --git a/kerberos-auth/test.json b/kerberos-auth/test.json
new file mode 100644
index 0000000..0d47a73
--- /dev/null
+++ b/kerberos-auth/test.json
@@ -0,0 +1,14 @@
+{
+ "name": "kerberos-auth",
+ "enabled": true,
+ "requiresSdk": true,
+ "version": "8.0",
+ "versionSpecific": false,
+ "type": "bash",
+ "cleanup": true,
+ "skipWhen": [
+ "ubi8-repos", // ubi repos don't contain kerberos utils
+ "ubi9-repos", // ubi repos don't contain kerberos utils
+ "ubi10-repos" // ubi repos don't contain kerberos utils
+ ]
+}
diff --git a/kerberos-auth/test.sh b/kerberos-auth/test.sh
new file mode 100755
index 0000000..f09e4f0
--- /dev/null
+++ b/kerberos-auth/test.sh
@@ -0,0 +1,171 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+IFS=$'\n\t'
+
+# Enable verbose output for debugging
+set -x
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+TEST_DIR=""
+KDC_PID=""
+ASPNET_SERVER_PID=""
+
+# Cleanup function
+cleanup() {
+ local exit_code=$?
+ set +e
+
+ echo "Cleaning up..."
+
+ # Kill server
+ if [[ -n "${ASPNET_SERVER_PID}" ]] && ps -p "${ASPNET_SERVER_PID}" > /dev/null 2>&1; then
+ echo "Stopping ASP.NET Core server (PID: ${ASPNET_SERVER_PID})"
+ kill "${ASPNET_SERVER_PID}" 2>/dev/null || true
+ sleep 1
+ kill -9 "${ASPNET_SERVER_PID}" 2>/dev/null || true
+ fi
+
+ # Kill KDC
+ if [[ -n "${KDC_PID}" ]] && ps -p "${KDC_PID}" > /dev/null 2>&1; then
+ echo "Stopping KDC (PID: ${KDC_PID})"
+ kill "${KDC_PID}" 2>/dev/null || true
+ sleep 1
+ kill -9 "${KDC_PID}" 2>/dev/null || true
+ elif [[ -n "${TEST_DIR}" ]] && [[ -f "${TEST_DIR}/kdc.pid" ]]; then
+ KDC_PID=$(cat "${TEST_DIR}/kdc.pid")
+ if ps -p "${KDC_PID}" > /dev/null 2>&1; then
+ echo "Stopping KDC from pidfile (PID: ${KDC_PID})"
+ kill "${KDC_PID}" 2>/dev/null || true
+ sleep 1
+ kill -9 "${KDC_PID}" 2>/dev/null || true
+ fi
+ fi
+
+ # Clean up temp directory
+ if [[ -n "${TEST_DIR}" ]] && [[ -d "${TEST_DIR}" ]]; then
+ echo "Removing temporary directory: ${TEST_DIR}"
+ rm -rf "${TEST_DIR}"
+ fi
+
+ if [[ ${exit_code} -ne 0 ]]; then
+ echo "Test FAILED with exit code ${exit_code}"
+ fi
+
+ exit ${exit_code}
+}
+
+trap cleanup EXIT INT TERM
+
+# Generate random values for isolation
+RANDOM_ID="${RANDOM}${RANDOM}"
+REALM="TEST${RANDOM_ID}.LOCAL"
+KDC_PORT=$((10000 + (RANDOM % 20000)))
+ASPNET_PORT=$((30000 + (RANDOM % 20000)))
+
+# Ensure ports are different
+while [[ ${ASPNET_PORT} -eq ${KDC_PORT} ]]; do
+ ASPNET_PORT=$((30000 + (RANDOM % 20000)))
+done
+
+echo "=========================================="
+echo "Kerberos Authentication Test"
+echo "=========================================="
+echo "Realm: ${REALM}"
+echo "KDC Port: ${KDC_PORT}"
+echo "ASP.NET Core Port: ${ASPNET_PORT}"
+echo "=========================================="
+
+# Create temporary directory
+TEST_DIR=$(mktemp -d -t kerberos-test-XXXXXX)
+echo "Test directory: ${TEST_DIR}"
+
+# Setup KDC
+echo ""
+echo "Setting up Kerberos KDC..."
+export KRB5_CONFIG="${TEST_DIR}/krb5.conf"
+export KRB5_KDC_PROFILE="${TEST_DIR}/kdc.conf"
+export KRB5CCNAME="FILE:${TEST_DIR}/krb5cc"
+
+bash "${SCRIPT_DIR}/setup-kdc.sh" "${TEST_DIR}" "${REALM}" "${KDC_PORT}"
+
+# Read KDC PID
+if [[ -f "${TEST_DIR}/kdc.pid" ]]; then
+ KDC_PID=$(cat "${TEST_DIR}/kdc.pid")
+ echo "KDC running with PID: ${KDC_PID}"
+fi
+
+# Acquire client credentials
+echo ""
+echo "Acquiring client Kerberos credentials..."
+export KRB5_KTNAME="${TEST_DIR}/client.keytab"
+kinit -kt "${KRB5_KTNAME}" "testclient@${REALM}"
+
+# Verify ticket
+echo ""
+echo "Verifying Kerberos ticket..."
+klist
+
+echo ""
+echo "=========================================="
+echo "ASP.NET Core with Kerberos"
+echo "=========================================="
+
+# Build client
+echo "Building client..."
+pushd "${SCRIPT_DIR}/client"
+dotnet build -c Release
+popd
+
+# Build ASP.NET Core server
+echo "Building ASP.NET Core server..."
+pushd "${SCRIPT_DIR}/aspnet-server"
+dotnet build -c Release
+popd
+
+# Start ASP.NET Core server
+echo "Starting ASP.NET Core server on port ${ASPNET_PORT}..."
+export KRB5_KTNAME="${TEST_DIR}/http.keytab"
+export SERVER_PORT="${ASPNET_PORT}"
+
+dotnet "${SCRIPT_DIR}"/aspnet-server/bin/Release/*/aspnet-server.dll &
+ASPNET_SERVER_PID=$!
+echo "ASP.NET Core server started (PID: ${ASPNET_SERVER_PID})"
+
+# Wait for server to be ready
+../run-until-success-with-backoff curl "http://localhost:${ASPNET_PORT}/" --negotiate -u : || {
+ echo "FAIL: ASP.NET Core server did not start properly"
+ exit 1
+}
+
+# Run client test
+echo "Running client test..."
+export KRB5_KTNAME="${TEST_DIR}/client.keytab"
+export SERVER_URL="http://localhost:${ASPNET_PORT}/"
+
+if dotnet "${SCRIPT_DIR}"/client/bin/Release/*/client.dll; then
+ echo ""
+ echo "======================================"
+ echo "ASP.NET Core Test: PASS"
+ echo "======================================"
+else
+ echo ""
+ echo "======================================"
+ echo "ASP.NET Core Test: FAIL"
+ echo "======================================"
+ exit 1
+fi
+
+# Stop ASP.NET Core server
+echo "Stopping ASP.NET Core server..."
+kill "${ASPNET_SERVER_PID}" 2>/dev/null || true
+sleep 1
+kill -9 "${ASPNET_SERVER_PID}" 2>/dev/null || true
+ASPNET_SERVER_PID=""
+
+echo ""
+echo "=========================================="
+echo "Kerberos Authentication Test: PASS"
+echo "=========================================="
+
+exit 0