diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..6b78bae Binary files /dev/null and b/.DS_Store differ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e79e9e4 --- /dev/null +++ b/.env.example @@ -0,0 +1,14 @@ +# Duo Universal C# Configuration +# Rename this file to .env on your server + +# Duo credentials from Admin Panel +DUO_CLIENT_ID=DIJAYTMEB36S4FIOXI7F +DUO_CLIENT_SECRET=Pp9UJnNA7CQ10wlP2CLyWTHW8n9KH6Xjefa1KQJu +DUO_API_HOST=api-8905b780.duosecurity.com +# Utilisation de l'IP publique directe (Duo nécessite HTTPS) +DUO_REDIRECT_URI=https://localhost:5001/duo_callback + +# ASP.NET Core settings +ASPNETCORE_ENVIRONMENT=Production +# IMPORTANT: Utilisez 0.0.0.0 pour être accessible via votre IP publique +ASPNETCORE_URLS=http://0.0.0.0:5000;https://0.0.0.0:5001 diff --git a/.gitignore b/.gitignore index ae5c4cd..127f556 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ .vscode */bin */obj +*.db +*.db-shm +*.db-wal +.env +.env.example diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..418a54b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +WORKDIR /src + +# Copy solution and projects for restore +COPY ["duo_universal_csharp.sln", "./"] +COPY ["DuoUniversal/DuoUniversal.csproj", "DuoUniversal/"] +COPY ["DuoUniversal.Example/DuoUniversal.Example.csproj", "DuoUniversal.Example/"] +COPY ["DuoUniversal.Tests/DuoUniversal.Tests.csproj", "DuoUniversal.Tests/"] + +RUN dotnet restore + +# Copy everything else +COPY . . + +# Build and publish +WORKDIR "/src/DuoUniversal.Example" +RUN dotnet build "DuoUniversal.Example.csproj" -c Release -o /app/build +RUN dotnet publish "DuoUniversal.Example.csproj" -c Release -o /app/publish /p:UseAppHost=false + +# Final stage +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +COPY --from=build /app/publish . +ENTRYPOINT ["dotnet", "DuoUniversal.Example.dll"] diff --git a/DuoUniversal.Example/.DS_Store b/DuoUniversal.Example/.DS_Store new file mode 100644 index 0000000..0fbdd64 Binary files /dev/null and b/DuoUniversal.Example/.DS_Store differ diff --git a/DuoUniversal.Example/Data/AppDbContext.cs b/DuoUniversal.Example/Data/AppDbContext.cs new file mode 100644 index 0000000..64d36f7 --- /dev/null +++ b/DuoUniversal.Example/Data/AppDbContext.cs @@ -0,0 +1,11 @@ +using Microsoft.EntityFrameworkCore; + +namespace DuoUniversal.Example.Data +{ + public class AppDbContext : DbContext + { + public AppDbContext(DbContextOptions options) : base(options) { } + + public DbSet Users { get; set; } + } +} diff --git a/DuoUniversal.Example/Data/DuoConfig.cs b/DuoUniversal.Example/Data/DuoConfig.cs new file mode 100644 index 0000000..96ae1b0 --- /dev/null +++ b/DuoUniversal.Example/Data/DuoConfig.cs @@ -0,0 +1,10 @@ +namespace DuoUniversal.Example.Data +{ + public class DuoConfig + { + public string ClientId { get; set; } + public string ClientSecret { get; set; } + public string ApiHost { get; set; } + public string RedirectUri { get; set; } + } +} diff --git a/DuoUniversal.Example/Data/SeedData.cs b/DuoUniversal.Example/Data/SeedData.cs new file mode 100644 index 0000000..cfc6905 --- /dev/null +++ b/DuoUniversal.Example/Data/SeedData.cs @@ -0,0 +1,45 @@ +using System.Linq; + +namespace DuoUniversal.Example.Data +{ + public static class SeedData + { + public static void Initialize(AppDbContext context) + { + context.Database.EnsureCreated(); + + if (!context.Users.Any(u => u.Username == "duouser")) + { + context.Users.Add(new User + { + Username = "duouser", + Password = "password123" + }); + } + + if (!context.Users.Any(u => u.Username == "Desktop_versus")) + { + context.Users.Add(new User + { + Username = "Desktop_versus", + Password = "password123" + }); + } + + for (int i = 1; i <= 15; i++) + { + string username = $"user{i}"; + if (!context.Users.Any(u => u.Username == username)) + { + context.Users.Add(new User + { + Username = username, + Password = "password123" + }); + } + } + + context.SaveChanges(); + } + } +} diff --git a/DuoUniversal.Example/Data/User.cs b/DuoUniversal.Example/Data/User.cs new file mode 100644 index 0000000..af5ddd3 --- /dev/null +++ b/DuoUniversal.Example/Data/User.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace DuoUniversal.Example.Data +{ + public class User + { + public int Id { get; set; } + + [Required] + public string Username { get; set; } + + [Required] + public string Password { get; set; } // Storing plain text/simple hash for demo purposes + } +} diff --git a/DuoUniversal.Example/DuoUniversal.Example.csproj b/DuoUniversal.Example/DuoUniversal.Example.csproj index af4db54..d45b61f 100644 --- a/DuoUniversal.Example/DuoUniversal.Example.csproj +++ b/DuoUniversal.Example/DuoUniversal.Example.csproj @@ -7,8 +7,16 @@ + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + - netcoreapp3.1;net6.0 + net8.0 diff --git a/DuoUniversal.Example/Pages/Callback.cshtml b/DuoUniversal.Example/Pages/Callback.cshtml index 8ee694c..0745da1 100644 --- a/DuoUniversal.Example/Pages/Callback.cshtml +++ b/DuoUniversal.Example/Pages/Callback.cshtml @@ -1,17 +1,164 @@ -@* SPDX-FileCopyrightText: 2022 Cisco Systems, Inc. and/or its affiliates *@ -@* SPDX-License-Identifier: BSD-3-Clause *@ - @page "/duo_callback" -@model CallbackModel +@model DuoUniversal.Example.Pages.CallbackModel +@{ + Layout = null; +} -
-