diff options
author | Tim <contact@bytim.eu> | 2025-04-19 19:33:04 +0200 |
---|---|---|
committer | Tim <contact@bytim.eu> | 2025-04-19 19:33:04 +0200 |
commit | 6a9657a10dc5ef3c4dfddf222284eec6c933ac83 (patch) | |
tree | a2b939a2e51ad04dd2635126be27d66c781666dd /VPNAuth.Server | |
parent | ff9b1e112ed14746ed74dfff1fb4c19efd5502d4 (diff) | |
download | VPNAuth-6a9657a10dc5ef3c4dfddf222284eec6c933ac83.tar.xz VPNAuth-6a9657a10dc5ef3c4dfddf222284eec6c933ac83.zip |
Diffstat (limited to 'VPNAuth.Server')
-rw-r--r-- | VPNAuth.Server/Database/AccessToken.cs | 1 | ||||
-rw-r--r-- | VPNAuth.Server/Database/AuthRequest.cs | 1 | ||||
-rw-r--r-- | VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.Designer.cs | 131 | ||||
-rw-r--r-- | VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.cs | 40 | ||||
-rw-r--r-- | VPNAuth.Server/Migrations/DatabaseModelSnapshot.cs | 8 | ||||
-rw-r--r-- | VPNAuth.Server/Pages/Auth.cshtml.cs | 3 | ||||
-rw-r--r-- | VPNAuth.Server/Pages/Dashboard.cshtml | 2 | ||||
-rw-r--r-- | VPNAuth.Server/Program.cs | 78 |
8 files changed, 256 insertions, 8 deletions
diff --git a/VPNAuth.Server/Database/AccessToken.cs b/VPNAuth.Server/Database/AccessToken.cs index 3cdc3ba..bb8fe7d 100644 --- a/VPNAuth.Server/Database/AccessToken.cs +++ b/VPNAuth.Server/Database/AccessToken.cs @@ -7,4 +7,5 @@ public class AccessToken public string ClientId { get; set; } public DateTime CreationTime { get; set; } public List<string> Scopes { get; set; } + public string Username { get; set; } } diff --git a/VPNAuth.Server/Database/AuthRequest.cs b/VPNAuth.Server/Database/AuthRequest.cs index 98fe001..11c05dc 100644 --- a/VPNAuth.Server/Database/AuthRequest.cs +++ b/VPNAuth.Server/Database/AuthRequest.cs @@ -11,4 +11,5 @@ public class AuthRequest public string CodeChallenge { get; set; } public string CodeChallengeMethod { get; set; } public bool Accepted { get; set; } + public string Username { get; set; } } diff --git a/VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.Designer.cs b/VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.Designer.cs new file mode 100644 index 0000000..8409c25 --- /dev/null +++ b/VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.Designer.cs @@ -0,0 +1,131 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using VPNAuth.Server.Database; + +#nullable disable + +namespace VPNAuth.Server.Migrations +{ + [DbContext(typeof(Database.Database))] + [Migration("20250419123149_AddUsernameFields")] + partial class AddUsernameFields + { + /// <inheritdoc /> + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.4"); + + modelBuilder.Entity("VPNAuth.Server.Database.AccessToken", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("ClientId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<DateTime>("CreationTime") + .HasColumnType("TEXT"); + + b.PrimitiveCollection<string>("Scopes") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<string>("Token") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<string>("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AccessTokens"); + }); + + modelBuilder.Entity("VPNAuth.Server.Database.AuthRequest", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<bool>("Accepted") + .HasColumnType("INTEGER"); + + b.Property<string>("ClientId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<string>("Code") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<string>("CodeChallenge") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<string>("CodeChallengeMethod") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<DateTime>("InitTime") + .HasColumnType("TEXT"); + + b.PrimitiveCollection<string>("Scopes") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<string>("State") + .HasColumnType("TEXT"); + + b.Property<string>("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AuthRequests"); + }); + + modelBuilder.Entity("VPNAuth.Server.Database.UserInformation", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("Email") + .HasColumnType("TEXT"); + + b.Property<string>("FamilyName") + .HasColumnType("TEXT"); + + b.Property<string>("GivenName") + .HasColumnType("TEXT"); + + b.Property<string>("Name") + .HasColumnType("TEXT"); + + b.Property<string>("Picture") + .HasColumnType("TEXT"); + + b.Property<string>("PreferredUsername") + .HasColumnType("TEXT"); + + b.Property<string>("Sub") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("UserInformation"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.cs b/VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.cs new file mode 100644 index 0000000..3d649bb --- /dev/null +++ b/VPNAuth.Server/Migrations/20250419123149_AddUsernameFields.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace VPNAuth.Server.Migrations +{ + /// <inheritdoc /> + public partial class AddUsernameFields : Migration + { + /// <inheritdoc /> + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn<string>( + name: "Username", + table: "AuthRequests", + type: "TEXT", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn<string>( + name: "Username", + table: "AccessTokens", + type: "TEXT", + nullable: false, + defaultValue: ""); + } + + /// <inheritdoc /> + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Username", + table: "AuthRequests"); + + migrationBuilder.DropColumn( + name: "Username", + table: "AccessTokens"); + } + } +} diff --git a/VPNAuth.Server/Migrations/DatabaseModelSnapshot.cs b/VPNAuth.Server/Migrations/DatabaseModelSnapshot.cs index e4643df..4dcce6b 100644 --- a/VPNAuth.Server/Migrations/DatabaseModelSnapshot.cs +++ b/VPNAuth.Server/Migrations/DatabaseModelSnapshot.cs @@ -38,6 +38,10 @@ namespace VPNAuth.Server.Migrations .IsRequired() .HasColumnType("TEXT"); + b.Property<string>("Username") + .IsRequired() + .HasColumnType("TEXT"); + b.HasKey("Id"); b.ToTable("AccessTokens"); @@ -78,6 +82,10 @@ namespace VPNAuth.Server.Migrations b.Property<string>("State") .HasColumnType("TEXT"); + b.Property<string>("Username") + .IsRequired() + .HasColumnType("TEXT"); + b.HasKey("Id"); b.ToTable("AuthRequests"); diff --git a/VPNAuth.Server/Pages/Auth.cshtml.cs b/VPNAuth.Server/Pages/Auth.cshtml.cs index bdcbc59..1f75492 100644 --- a/VPNAuth.Server/Pages/Auth.cshtml.cs +++ b/VPNAuth.Server/Pages/Auth.cshtml.cs @@ -44,7 +44,8 @@ public class Auth : PageModel Scopes = Request.Query["scope"].ToString().Split(" ").ToList(), CodeChallenge = Request.Query["code_challenge"]!, CodeChallengeMethod = Request.Query["code_challenge_method"]!, - Accepted = false + Accepted = false, + Username = User!.Username! }); db.SaveChanges(); } diff --git a/VPNAuth.Server/Pages/Dashboard.cshtml b/VPNAuth.Server/Pages/Dashboard.cshtml index 38f9c7e..78f6846 100644 --- a/VPNAuth.Server/Pages/Dashboard.cshtml +++ b/VPNAuth.Server/Pages/Dashboard.cshtml @@ -35,7 +35,7 @@ <h2>VPNAuth</h2> <p>Hey, @configUser.Username!</p> <h3>User settings</h3> - <form hx-post="/user-info" hx-swap="none" hx-trigger="change"> + <form hx-post="/user-info-settings" hx-swap="none" hx-trigger="change"> <table style="margin-left: auto; margin-right: auto;"> <tbody> <tr> diff --git a/VPNAuth.Server/Program.cs b/VPNAuth.Server/Program.cs index 822aba7..beae428 100644 --- a/VPNAuth.Server/Program.cs +++ b/VPNAuth.Server/Program.cs @@ -36,6 +36,12 @@ app.MapGet("/accept-auth/{id}", async (HttpContext context, int id) => return; } + if (authRequest.Username != context.GetUser()?.Username) + { + context.Response.StatusCode = StatusCodes.Status403Forbidden; + return; + } + authRequest.Accepted = true; db.SaveChanges(); @@ -80,7 +86,8 @@ app.MapPost("/access-token", async (HttpContext context) => ClientId = authRequest.ClientId, Scopes = authRequest.Scopes, CreationTime = DateTime.Now, - Token = PkceUtils.GenerateToken() + Token = PkceUtils.GenerateToken(), + Username = authRequest.Username }); db.SaveChanges(); @@ -92,7 +99,7 @@ app.MapPost("/access-token", async (HttpContext context) => }); }); -app.MapPost("/user-info", async (HttpContext context) => +app.MapPost("/user-info-settings", async (HttpContext context) => { using var db = new Database(); @@ -103,8 +110,10 @@ app.MapPost("/user-info", async (HttpContext context) => context.Response.StatusCode = StatusCodes.Status401Unauthorized; } - UserInformation? userInformation = db.UserInformation.Where(user => user.Sub == configUser!.Username) - .ToList().FirstOrDefault() ?? db.Add(new UserInformation + UserInformation? userInformation = db.UserInformation + .Where(user => user.Sub == configUser!.Username) + .ToList() + .FirstOrDefault() ?? db.Add(new UserInformation { Sub = configUser!.Username }).Entity; @@ -120,15 +129,72 @@ app.MapPost("/user-info", async (HttpContext context) => if (context.Request.Form.ContainsKey("email")) userInformation.Email = context.Request.Form["email"]!; - + if (context.Request.Form.ContainsKey("picture")) userInformation.Picture = context.Request.Form["picture"]!; - + userInformation.Name = userInformation.GivenName + " " + userInformation.FamilyName; db.SaveChanges(); }); +app.Map("/user-info", (HttpContext context) => +{ + if (context.Request.Method != "GET" && context.Request.Method != "POST") + { + context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; + return; + } + + var tokenHeader = context.Request.Headers["Authorization"].First()?.Split(" "); + + if (tokenHeader?.Length == 1 || tokenHeader?[0] != "Bearer") + { + context.Response.StatusCode = StatusCodes.Status400BadRequest; + return; + } + + if (tokenHeader.Length >= 2) + { + context.Response.StatusCode = StatusCodes.Status401Unauthorized; + return; + } + + using var db = new Database(); + var tokenDbEntry = db.AccessTokens + .Where(tokenEntry => tokenEntry.Token == tokenHeader[1]) + .ToList() + .FirstOrDefault(); + + if (tokenDbEntry == null) + { + context.Response.StatusCode = StatusCodes.Status403Forbidden; + return; + } + + var userInformation = db.UserInformation + .Where(entry => entry.Sub == tokenDbEntry.Username) + .ToList() + .FirstOrDefault(); + + if (userInformation == null) + { + context.Response.StatusCode = StatusCodes.Status204NoContent; + return; + } + + context.Response.WriteAsJsonAsync(new UserInfo + { + Email = userInformation.Email, + GivenName = userInformation.GivenName, + FamilyName = userInformation.FamilyName, + Name = userInformation.Name, + Picture = userInformation.Picture, + PreferredUsername = userInformation.PreferredUsername, + Sub = userInformation.Sub + }); +}); + app.MapStaticAssets(); app.MapRazorPages() .WithStaticAssets(); |