diff --git a/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Dockerfile b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Dockerfile
new file mode 100644
index 00000000..675da5dd
--- /dev/null
+++ b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Dockerfile
@@ -0,0 +1,29 @@
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+USER app
+WORKDIR /app
+EXPOSE 8080
+EXPOSE 8081
+EXPOSE 1935
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+ARG BUILD_CONFIGURATION=Release
+WORKDIR /src
+COPY ["samples/LiveStreamingServerNet.HlsAuthenticationDemo/LiveStreamingServerNet.HlsAuthenticationDemo.csproj", "samples/LiveStreamingServerNet.HlsAuthenticationDemo/"]
+COPY ["src/LiveStreamingServerNet.StreamProcessor/LiveStreamingServerNet.StreamProcessor.csproj", "src/LiveStreamingServerNet.StreamProcessor/"]
+COPY ["src/LiveStreamingServerNet.Rtmp/LiveStreamingServerNet.Rtmp.csproj", "src/LiveStreamingServerNet.Rtmp/"]
+COPY ["src/LiveStreamingServerNet.Networking/LiveStreamingServerNet.Networking.csproj", "src/LiveStreamingServerNet.Networking/"]
+COPY ["src/LiveStreamingServerNet.Utilities/LiveStreamingServerNet.Utilities.csproj", "src/LiveStreamingServerNet.Utilities/"]
+COPY ["src/LiveStreamingServerNet/LiveStreamingServerNet.csproj", "src/LiveStreamingServerNet/"]
+RUN dotnet restore "./samples/LiveStreamingServerNet.HlsAuthenticationDemo/LiveStreamingServerNet.HlsAuthenticationDemo.csproj"
+COPY . .
+WORKDIR "/src/samples/LiveStreamingServerNet.HlsAuthenticationDemo"
+RUN dotnet build "./LiveStreamingServerNet.HlsAuthenticationDemo.csproj" -c $BUILD_CONFIGURATION -o /app/build
+
+FROM build AS publish
+ARG BUILD_CONFIGURATION=Release
+RUN dotnet publish "./LiveStreamingServerNet.HlsAuthenticationDemo.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "LiveStreamingServerNet.HlsAuthenticationDemo.dll"]
\ No newline at end of file
diff --git a/samples/LiveStreamingServerNet.HlsAuthenticationDemo/LiveStreamingServerNet.HlsAuthenticationDemo.csproj b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/LiveStreamingServerNet.HlsAuthenticationDemo.csproj
new file mode 100644
index 00000000..49b2c831
--- /dev/null
+++ b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/LiveStreamingServerNet.HlsAuthenticationDemo.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net8.0
+ enable
+ enable
+ true
+ false
+ false
+ Linux
+ ..\..
+ -p 1935:1935 -p 8080:8080
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Program.cs b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Program.cs
new file mode 100644
index 00000000..8e5e994e
--- /dev/null
+++ b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Program.cs
@@ -0,0 +1,94 @@
+using LiveStreamingServerNet.Networking.Helpers;
+using LiveStreamingServerNet.Rtmp;
+using LiveStreamingServerNet.StreamProcessor.AspNetCore.Configurations;
+using LiveStreamingServerNet.StreamProcessor.AspNetCore.Installer;
+using LiveStreamingServerNet.StreamProcessor.Installer;
+using Microsoft.IdentityModel.Tokens;
+using System.Net;
+using System.Text;
+
+namespace LiveStreamingServerNet.HlsAuthenticationDemo
+{
+ public class Program
+ {
+ public static async Task Main(string[] args)
+ {
+ using var liveStreamingServer = CreateLiveStreamingServer();
+
+ var builder = WebApplication.CreateBuilder(args);
+
+ builder.Services.AddBackgroundServer(liveStreamingServer, new IPEndPoint(IPAddress.Any, 1935));
+
+ builder.Services.AddCors(options =>
+ options.AddDefaultPolicy(policy =>
+ policy.AllowAnyHeader()
+ .AllowAnyOrigin()
+ .AllowAnyMethod()
+ )
+ );
+
+ //
+ builder.Services.AddAuthentication()
+ .AddJwtBearer(options =>
+ {
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ValidateIssuer = false,
+ ValidateAudience = false,
+ ValidateLifetime = false,
+ ValidateIssuerSigningKey = true,
+ IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
+ "THIS_IS_A_SUPER_SECRET_KEY_FOR_DEMO_PURPOSE_ONLY")),
+ };
+ }
+ );
+
+ builder.Services.AddAuthorization();
+
+ var app = builder.Build();
+
+ app.UseAuthorization();
+
+ app.UseAuthentication();
+
+ app.UseCors();
+
+ // Given that the scheme is https, the port is 7138, and the stream path is live/demo,
+ // the HLS stream will be available at https://localhost:7138/hls/live/demo/output.m3u8
+ app.UseHlsFiles(liveStreamingServer, new HlsServingOptions
+ {
+ RequestPath = "/hls",
+
+ // Use bearer token authentication for HLS files
+ OnProcessRequestAsync = async (context) =>
+ {
+ if (context.Context.User.Identity?.IsAuthenticated != true)
+ {
+ context.Context.Response.StatusCode = StatusCodes.Status401Unauthorized;
+ await context.Context.Response.CompleteAsync();
+
+ context.Context.RequestServices
+ .GetRequiredService>()
+ .LogWarning($"Unauthorized request for {context.StreamPath} from {context.Context.Connection.RemoteIpAddress}");
+ }
+ }
+ });
+
+ await app.RunAsync();
+ }
+
+ private static ILiveStreamingServer CreateLiveStreamingServer()
+ {
+ return LiveStreamingServerBuilder.Create()
+ .ConfigureRtmpServer(options => options
+ .Configure(options => options.EnableGopCaching = false)
+ .AddVideoCodecFilter(builder => builder.Include(VideoCodec.AVC))
+ .AddAudioCodecFilter(builder => builder.Include(AudioCodec.AAC))
+ .AddStreamProcessor()
+ .AddHlsTransmuxer()
+ )
+ .ConfigureLogging(options => options.AddConsole())
+ .Build();
+ }
+ }
+}
diff --git a/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Properties/launchSettings.json b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Properties/launchSettings.json
new file mode 100644
index 00000000..c5e48552
--- /dev/null
+++ b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/Properties/launchSettings.json
@@ -0,0 +1,48 @@
+{
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "http://localhost:5010"
+ },
+ "https": {
+ "commandName": "Project",
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "https://localhost:7138;http://localhost:5010"
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Container (Dockerfile)": {
+ "commandName": "Docker",
+ "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
+ "environmentVariables": {
+ "ASPNETCORE_HTTPS_PORTS": "8081",
+ "ASPNETCORE_HTTP_PORTS": "8080"
+ },
+ "publishAllPorts": true,
+ "useSSL": true
+ }
+ },
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:40329",
+ "sslPort": 44320
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/LiveStreamingServerNet.HlsAuthenticationDemo/appsettings.Development.json b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/appsettings.Development.json
new file mode 100644
index 00000000..0c208ae9
--- /dev/null
+++ b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/samples/LiveStreamingServerNet.HlsAuthenticationDemo/appsettings.json b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/appsettings.json
new file mode 100644
index 00000000..10f68b8c
--- /dev/null
+++ b/samples/LiveStreamingServerNet.HlsAuthenticationDemo/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}