Add SGU credential provider and authentication broker
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace SGU.CredentialProvider.Tests;
|
||||
|
||||
public sealed class BrokerClientTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task SendsTheOriginalPasswordWithoutDerivation()
|
||||
{
|
||||
const string original = "Exacta-Árbol-🔐-27!";
|
||||
CapturingHandler handler = new(HttpStatusCode.OK, """
|
||||
{"domain":"LCI","username":"DO123456","upn":"DO123456@lci.lasalle.mx","created":true,"moved":false}
|
||||
""");
|
||||
using BrokerClient client = new(CreateSettings(), handler);
|
||||
|
||||
BrokerDecision decision = await client.AuthenticateAsync(
|
||||
"DO123456",
|
||||
original,
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(BrokerDecisionKind.Authorized, decision.Kind);
|
||||
using JsonDocument requestJson = JsonDocument.Parse(handler.RequestBody);
|
||||
Assert.Equal(original, requestJson.RootElement.GetProperty("password").GetString());
|
||||
Assert.DoesNotContain("derived", handler.RequestBody, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExplicitUnauthorizedResponseStopsTheLogin()
|
||||
{
|
||||
using BrokerClient client = new(
|
||||
CreateSettings(),
|
||||
new CapturingHandler(HttpStatusCode.Unauthorized, "{\"code\":\"INVALID_INSTITUTIONAL_CREDENTIALS\"}"));
|
||||
|
||||
BrokerDecision decision = await client.AuthenticateAsync(
|
||||
"AL123456",
|
||||
"Wrong",
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(BrokerDecisionKind.InvalidCredentials, decision.Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BrokerOutageRequestsWindowsCachedCredentialFallback()
|
||||
{
|
||||
using BrokerClient client = new(
|
||||
CreateSettings(),
|
||||
new CapturingHandler(HttpStatusCode.ServiceUnavailable, "{\"code\":\"NTLM_UPSTREAM_ERROR\"}"));
|
||||
|
||||
BrokerDecision decision = await client.AuthenticateAsync(
|
||||
"AD123456",
|
||||
"LastKnown",
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(BrokerDecisionKind.Unavailable, decision.Kind);
|
||||
}
|
||||
|
||||
private static ProviderSettings CreateSettings() => new()
|
||||
{
|
||||
BrokerEndpoint = new Uri("https://broker.example.test/v1/authenticate"),
|
||||
DomainNetbios = "LCI",
|
||||
TimeoutSeconds = 5,
|
||||
ClientCertificateThumbprint = new string('A', 40),
|
||||
ServerCertificateThumbprint = new string('B', 40)
|
||||
};
|
||||
|
||||
private sealed class CapturingHandler(HttpStatusCode statusCode, string responseBody) : HttpMessageHandler
|
||||
{
|
||||
public string RequestBody { get; private set; } = string.Empty;
|
||||
|
||||
protected override async Task<HttpResponseMessage> SendAsync(
|
||||
HttpRequestMessage request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
RequestBody = request.Content is null
|
||||
? string.Empty
|
||||
: await request.Content.ReadAsStringAsync(cancellationToken);
|
||||
|
||||
return new HttpResponseMessage(statusCode)
|
||||
{
|
||||
Content = new StringContent(responseBody, Encoding.UTF8, "application/json")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\SGU.CredentialProvider\SGU.CredentialProvider.csproj" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.9.0" />
|
||||
<PackageReference Include="xunit.v3" Version="4.0.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user