Improve SGU logon resilience and client UX

This commit is contained in:
2026-09-01 10:37:40 -06:00
parent 3d0897316d
commit da01343985
27 changed files with 869 additions and 37 deletions
@@ -78,6 +78,13 @@ public sealed class BrokerOptions
throw new InvalidOperationException($"The OU mapping for {role} must be beneath BaseDn.");
}
}
if (!string.IsNullOrWhiteSpace(Directory.RemoteDesktopGroupDn) &&
(!Directory.RemoteDesktopGroupDn.StartsWith("CN=", StringComparison.OrdinalIgnoreCase) ||
!Directory.RemoteDesktopGroupDn.EndsWith($",{Directory.BaseDn}", StringComparison.OrdinalIgnoreCase)))
{
throw new InvalidOperationException("RemoteDesktopGroupDn must identify a group beneath BaseDn.");
}
}
private static bool IsCertificateThumbprint(string value)
@@ -130,6 +137,8 @@ public sealed class ActiveDirectoryOptions
public string AdministrativeOuDn { get; init; } = "OU=Administrativos,OU=Usuarios-SGU,DC=lci,DC=lasalle,DC=mx";
public string RemoteDesktopGroupDn { get; init; } = string.Empty;
public bool CreateMissingOus { get; init; }
public string GetOuDn(InstitutionalRole role) => role switch
@@ -101,6 +101,7 @@ public sealed class ActiveDirectorySynchronizer(BrokerOptions options) : IActive
user.CommitChanges();
TryApplyProfile(user, identity, profile);
TryEnsureRemoteDesktopGroupMembership(user);
return new DirectorySyncResult(
options.DomainNetbios,
@@ -163,6 +164,37 @@ public sealed class ActiveDirectorySynchronizer(BrokerOptions options) : IActive
}
}
private void TryEnsureRemoteDesktopGroupMembership(DirectoryEntry user)
{
if (string.IsNullOrWhiteSpace(options.RemoteDesktopGroupDn))
{
return;
}
try
{
user.RefreshCache(["distinguishedName"]);
string? userDn = Convert.ToString(user.Properties["distinguishedName"].Value);
if (string.IsNullOrWhiteSpace(userDn))
{
return;
}
using DirectoryEntry group = Bind(options.RemoteDesktopGroupDn);
_ = group.NativeObject;
if (!group.Properties["member"].Contains(userDn))
{
group.Properties["member"].Add(userDn);
group.CommitChanges();
}
}
catch
{
// Remote access is lab policy and must not invalidate a completed
// password synchronization if the optional group is unavailable.
}
}
private DirectoryEntry BindOrCreateOu(string ouDn, DirectoryEntry root)
{
try
@@ -1,5 +1,4 @@
using System.Net;
using System.Text;
using SGU.AuthBroker.Core.Authentication;
using SGU.AuthBroker.Core.Identity;
using SGU.AuthBroker.Core.Profiles;
@@ -202,20 +201,9 @@ public sealed class NtlmCredentialValidator(BrokerOptions options) : INtlmCreden
buffer.Write(chunk, 0, read);
}
string? charset = content.Headers.ContentType?.CharSet?.Trim('"', '\'');
Encoding encoding;
try
{
encoding = string.IsNullOrWhiteSpace(charset)
? Encoding.UTF8
: Encoding.GetEncoding(charset);
}
catch (ArgumentException)
{
encoding = Encoding.UTF8;
}
return encoding.GetString(buffer.GetBuffer(), 0, checked((int)buffer.Length));
return SguHtmlDecoder.Decode(
buffer.GetBuffer().AsSpan(0, checked((int)buffer.Length)),
content.Headers.ContentType?.CharSet);
}
private static bool IsAllowedHttpsUri(Uri uri, HashSet<string> allowedHosts) =>
+1
View File
@@ -46,6 +46,7 @@
"ProfessorOuDn": "OU=Docentes,OU=Usuarios-SGU,DC=lci,DC=lasalle,DC=mx",
"StudentOuDn": "OU=Alumnos,OU=Usuarios-SGU,DC=lci,DC=lasalle,DC=mx",
"AdministrativeOuDn": "OU=Administrativos,OU=Usuarios-SGU,DC=lci,DC=lasalle,DC=mx",
"RemoteDesktopGroupDn": "",
"CreateMissingOus": false
}
}