From 5cf951e908d30214a62152564416a3f0482c651a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Thu, 21 Nov 2024 22:04:13 +0100 Subject: [PATCH] [backend/razor] Add TOTP 2FA support to OAuth page --- .../Pages/OAuth/Authorize.cshtml | 130 +++++++++++++----- .../Pages/OAuth/Authorize.cshtml.cs | 49 ++++++- .../Pages/OAuth/Authorize.cshtml.css | 11 ++ 3 files changed, 155 insertions(+), 35 deletions(-) diff --git a/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml b/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml index a91fe33b..9798fe93 100644 --- a/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml +++ b/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml @@ -17,52 +17,114 @@ } -
-
- Feature flags: -
-
- - -
-
- - -
-
- - -
- @if (Model.AuthenticatedUsers.Count > 0) - { -
- @foreach (var user in Model.AuthenticatedUsers) + @if (Model.TwoFactorFormData is { } data) + { + +
+ Feature flags: +
+
+ @if (data.SupportsHtmlFormatting) { - + + } + else + { + + } +
-
- Alternatively, sign in with to a different account below: +
+ @if (data.AutoDetectQuotes) + { + + + } + else + { + + } + +
+
+ @if (data.IsPleroma) + { + + + } + else + { + + } +
- - - } - else - {
Log in below to confirm this:
- - - } - - + + + + + + + + } + else + { +
+
+ Feature flags: +
+
+ + +
+
+ + +
+
+ + +
+ @if (Model.AuthenticatedUsers.Count > 0) + { +
+ @foreach (var user in Model.AuthenticatedUsers) + { + + } +
+
+ Alternatively, sign in with to a different account below: +
+ + + } + else + { +
+ Log in below to confirm this: +
+ + + } + + +
+ }
} else if (Model.Token.RedirectUri == "urn:ietf:wg:oauth:2.0:oob") {
- Your code is:
@Model.Token.Code
+ Your code is: +
@Model.Token.Code
} else diff --git a/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.cs b/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.cs index e82b9d61..9930223d 100644 --- a/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.cs +++ b/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.cs @@ -3,6 +3,7 @@ using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Middleware; +using Iceshrimp.Shared.Schemas.Web; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; @@ -30,6 +31,8 @@ public class AuthorizeModel(DatabaseContext db) : PageModel [MemberNotNull(nameof(Scopes))] set => Scopes = value.Split(' ').ToList(); } + public LoginData? TwoFactorFormData = null; + public async Task OnGet() { if (ResponseType == null || ClientId == null || RedirectUri == null) @@ -53,7 +56,7 @@ public class AuthorizeModel(DatabaseContext db) : PageModel } public async Task OnPost( - [FromForm] string? username, [FromForm] string? password, [FromForm] string? userId, + [FromForm] string? username, [FromForm] string? password, [FromForm] string? totp, [FromForm] string? userId, [FromForm] bool supportsHtmlFormatting, [FromForm] bool autoDetectQuotes, [FromForm] bool isPleroma ) { @@ -77,6 +80,25 @@ public class AuthorizeModel(DatabaseContext db) : PageModel throw Forbidden(); if (AuthHelpers.ComparePassword(password, userSettings.Password) == false) throw Forbidden(); + + if (userSettings.TwoFactorEnabled) + { + if (!string.IsNullOrWhiteSpace(totp)) + { + if (userSettings.TwoFactorSecret == null) + throw new Exception("2FA is enabled but secret is null"); + if (!TotpHelper.Validate(userSettings.TwoFactorSecret, totp)) + { + SetTwoFactorFormData(); + return; + } + } + else + { + SetTwoFactorFormData(); + return; + } + } } var token = new OauthToken @@ -99,5 +121,30 @@ public class AuthorizeModel(DatabaseContext db) : PageModel await db.SaveChangesAsync(); Token = token; + return; + + void SetTwoFactorFormData() + { + TwoFactorFormData = new LoginData + { + Username = username, + Password = password, + AutoDetectQuotes = autoDetectQuotes, + SupportsHtmlFormatting = supportsHtmlFormatting, + IsPleroma = isPleroma + }; + + Response.Headers.CacheControl = "private, no-store, no-cache"; + Response.Headers.Pragma = "no-cache"; + } + } + + public class LoginData + { + public required string Username; + public required string Password; + public required bool SupportsHtmlFormatting; + public required bool AutoDetectQuotes; + public required bool IsPleroma; } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.css b/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.css index 656e0dc2..5f99e055 100644 --- a/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.css +++ b/Iceshrimp.Backend/Pages/OAuth/Authorize.cshtml.css @@ -12,4 +12,15 @@ .margin-top-10px { margin-top: 10px; +} + +.hidden-input { + position: absolute; + top: -10px; + left: -10px; + height: 0; + width: 0; + padding: 0; + margin: 0; + pointer-events: none; } \ No newline at end of file