jellyfin/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs

157 lines
5.7 KiB
C#
Raw Normal View History

using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AutoFixture;
using AutoFixture.AutoMoq;
using Jellyfin.Api.Auth;
using Jellyfin.Api.Constants;
2020-05-20 19:07:53 +02:00
using Jellyfin.Data.Entities;
2020-05-13 04:10:35 +02:00
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
namespace Jellyfin.Api.Tests.Auth
{
public class CustomAuthenticationHandlerTests
{
private readonly IFixture _fixture;
private readonly Mock<IAuthService> _jellyfinAuthServiceMock;
private readonly CustomAuthenticationHandler _sut;
private readonly AuthenticationScheme _scheme;
public CustomAuthenticationHandlerTests()
{
2019-12-22 23:36:11 +01:00
var fixtureCustomizations = new AutoMoqCustomization
{
ConfigureMembers = true
};
_fixture = new Fixture().Customize(fixtureCustomizations);
AllowFixtureCircularDependencies();
_jellyfinAuthServiceMock = _fixture.Freeze<Mock<IAuthService>>();
2020-06-16 22:12:40 +02:00
var optionsMonitorMock = _fixture.Freeze<Mock<IOptionsMonitor<AuthenticationSchemeOptions>>>();
var serviceProviderMock = _fixture.Freeze<Mock<IServiceProvider>>();
var authenticationServiceMock = _fixture.Freeze<Mock<IAuthenticationService>>();
_fixture.Register<ILoggerFactory>(() => new NullLoggerFactory());
2020-06-16 22:12:40 +02:00
serviceProviderMock.Setup(s => s.GetService(typeof(IAuthenticationService)))
.Returns(authenticationServiceMock.Object);
2020-06-16 22:12:40 +02:00
optionsMonitorMock.Setup(o => o.Get(It.IsAny<string>()))
.Returns(new AuthenticationSchemeOptions
{
ForwardAuthenticate = null
});
2020-06-16 22:12:40 +02:00
HttpContext context = new DefaultHttpContext
{
2020-06-16 22:12:40 +02:00
RequestServices = serviceProviderMock.Object
};
_scheme = new AuthenticationScheme(
_fixture.Create<string>(),
null,
typeof(CustomAuthenticationHandler));
_sut = _fixture.Create<CustomAuthenticationHandler>();
2020-06-16 22:12:40 +02:00
_sut.InitializeAsync(_scheme, context).Wait();
}
[Fact]
public async Task HandleAuthenticateAsyncShouldProvideNoResultOnAuthenticationException()
{
var errorMessage = _fixture.Create<string>();
_jellyfinAuthServiceMock.Setup(
a => a.Authenticate(
2020-06-16 22:12:40 +02:00
It.IsAny<HttpRequest>()))
.Throws(new AuthenticationException(errorMessage));
var authenticateResult = await _sut.AuthenticateAsync();
Assert.False(authenticateResult.Succeeded);
Assert.True(authenticateResult.None);
}
[Fact]
public async Task HandleAuthenticateAsyncShouldSucceedWithUser()
{
SetupUser();
var authenticateResult = await _sut.AuthenticateAsync();
Assert.True(authenticateResult.Succeeded);
Assert.Null(authenticateResult.Failure);
}
[Fact]
public async Task HandleAuthenticateAsyncShouldAssignNameClaim()
{
2020-06-16 22:12:40 +02:00
var authorizationInfo = SetupUser();
var authenticateResult = await _sut.AuthenticateAsync();
Assert.True(authenticateResult.Principal?.HasClaim(ClaimTypes.Name, authorizationInfo.User.Username));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task HandleAuthenticateAsyncShouldAssignRoleClaim(bool isAdmin)
{
2020-06-16 22:12:40 +02:00
var authorizationInfo = SetupUser(isAdmin);
var authenticateResult = await _sut.AuthenticateAsync();
2020-06-16 22:12:40 +02:00
var expectedRole = authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User;
Assert.True(authenticateResult.Principal?.HasClaim(ClaimTypes.Role, expectedRole));
}
[Fact]
public async Task HandleAuthenticateAsyncShouldAssignTicketCorrectScheme()
{
SetupUser();
var authenticatedResult = await _sut.AuthenticateAsync();
Assert.Equal(_scheme.Name, authenticatedResult.Ticket?.AuthenticationScheme);
}
2020-06-16 22:12:40 +02:00
private AuthorizationInfo SetupUser(bool isAdmin = false)
{
2020-06-16 22:12:40 +02:00
var authorizationInfo = _fixture.Create<AuthorizationInfo>();
authorizationInfo.User = _fixture.Create<User>();
2021-03-18 02:24:14 +01:00
authorizationInfo.User.AddDefaultPermissions();
authorizationInfo.User.AddDefaultPreferences();
2020-06-16 22:12:40 +02:00
authorizationInfo.User.SetPermission(PermissionKind.IsAdministrator, isAdmin);
2020-10-29 00:57:16 +01:00
authorizationInfo.IsApiKey = false;
authorizationInfo.HasToken = true;
authorizationInfo.Token = "fake-token";
_jellyfinAuthServiceMock.Setup(
a => a.Authenticate(
2020-06-16 22:12:40 +02:00
It.IsAny<HttpRequest>()))
2021-05-21 05:56:59 +02:00
.Returns(Task.FromResult(authorizationInfo));
2020-06-16 22:12:40 +02:00
return authorizationInfo;
}
private void AllowFixtureCircularDependencies()
{
// A circular dependency exists in the User entity around parent folders,
// this allows Autofixture to generate a User regardless, rather than throw
// an error.
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
}
}
}