Files
SGU-CredentialProvider/tests/SGU.AuthBroker.Core.Tests/AuthenticationWorkflowTests.cs
T

115 lines
3.9 KiB
C#

using SGU.AuthBroker.Core.Authentication;
using SGU.AuthBroker.Core.Directory;
using SGU.AuthBroker.Core.Identity;
using SGU.AuthBroker.Core.Profiles;
using Xunit;
namespace SGU.AuthBroker.Core.Tests;
public sealed class AuthenticationWorkflowTests
{
[Fact]
public async Task PassesTheExactOriginalPasswordToNtlmAndActiveDirectory()
{
const string original = "Árbol-Exacto-🔐-NoDerivar-27!";
InstitutionalProfile profile = new(
EmployeeNumber: "123456",
DisplayName: "Persona de Prueba",
Email: "persona@lasalle.mx",
JobTitle: "DOCENTE",
Department: "FACULTAD DE PRUEBA");
CapturingNtlmValidator ntlm = new(NtlmValidationResult.Valid(profile));
CapturingDirectorySynchronizer directory = new();
AuthenticationWorkflow workflow = new(ntlm, directory);
AuthenticationFlowResult result = await workflow.AuthenticateAsync(
"do123456",
original,
TestContext.Current.CancellationToken);
Assert.Equal(AuthenticationFlowOutcome.Authorized, result.Outcome);
Assert.Same(original, ntlm.Password);
Assert.Same(original, directory.Password);
Assert.Equal("DO123456", ntlm.Identity?.UserName);
Assert.Equal(InstitutionalRole.Professor, directory.Identity?.Role);
Assert.Same(profile, directory.Profile);
}
[Fact]
public async Task InvalidNtlmCredentialsNeverReachActiveDirectory()
{
CapturingDirectorySynchronizer directory = new();
AuthenticationWorkflow workflow = new(
new CapturingNtlmValidator(NtlmValidationResult.Invalid()),
directory);
AuthenticationFlowResult result = await workflow.AuthenticateAsync(
"AL123456",
"Wrong",
TestContext.Current.CancellationToken);
Assert.Equal(AuthenticationFlowOutcome.InvalidCredentials, result.Outcome);
Assert.Null(directory.Password);
}
[Fact]
public async Task NtlmOutageIsReportedAsUnavailableForProviderFallback()
{
CapturingDirectorySynchronizer directory = new();
AuthenticationWorkflow workflow = new(
new CapturingNtlmValidator(NtlmValidationResult.Unavailable()),
directory);
AuthenticationFlowResult result = await workflow.AuthenticateAsync(
"AD123456",
"LastKnownPassword",
TestContext.Current.CancellationToken);
Assert.Equal(AuthenticationFlowOutcome.Unavailable, result.Outcome);
Assert.Null(directory.Password);
}
private sealed class CapturingNtlmValidator(NtlmValidationResult result) : INtlmCredentialValidator
{
public UserIdentity? Identity { get; private set; }
public string? Password { get; private set; }
public Task<NtlmValidationResult> ValidateAsync(
UserIdentity identity,
string password,
CancellationToken cancellationToken)
{
Identity = identity;
Password = password;
return Task.FromResult(result);
}
}
private sealed class CapturingDirectorySynchronizer : IActiveDirectorySynchronizer
{
public UserIdentity? Identity { get; private set; }
public string? Password { get; private set; }
public InstitutionalProfile? Profile { get; private set; }
public Task<DirectorySyncResult> SynchronizeAsync(
UserIdentity identity,
InstitutionalProfile? profile,
string password,
CancellationToken cancellationToken)
{
Identity = identity;
Profile = profile;
Password = password;
return Task.FromResult(new DirectorySyncResult(
"LCI",
identity.UserName,
$"{identity.UserName}@lci.lasalle.mx",
true,
false));
}
}
}