using System.Security.Cryptography; using AutoFixture; using Bit.Core.Tokens; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using Bit.Test.Common.Helpers; using Microsoft.AspNetCore.DataProtection; using Xunit; namespace Bit.Core.Test.Tokens; [SutProviderCustomize] public class DataProtectorTokenFactoryTests { public static SutProvider> GetSutProvider() { var fixture = new Fixture(); return new SutProvider>(fixture) .SetDependency(fixture.Create()) .Create(); } [Theory, BitAutoData] public void CanRoundTripTokenables(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable); var recoveredTokenable = sutProvider.Sut.Unprotect(token); AssertHelper.AssertPropertyEqual(tokenable, recoveredTokenable); } [Theory, BitAutoData] public void PrependsClearText(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable); Assert.StartsWith(sutProvider.GetDependency("clearTextPrefix"), token); } [Theory, BitAutoData] public void EncryptsToken(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var prefix = sutProvider.GetDependency("clearTextPrefix"); var token = sutProvider.Sut.Protect(tokenable); Assert.NotEqual(new Token(token).RemovePrefix(prefix), tokenable.ToToken()); } [Theory, BitAutoData] public void ThrowsIfUnprotectFails(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable); token += "stuff to make sure decryption fails"; Assert.Throws(() => sutProvider.Sut.Unprotect(token)); } [Theory, BitAutoData] public void TryUnprotect_FalseIfUnprotectFails(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable) + "fail decryption"; var result = sutProvider.Sut.TryUnprotect(token, out var data); Assert.False(result); Assert.Null(data); } [Theory, BitAutoData] public void TokenValid_FalseIfUnprotectFails(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable) + "fail decryption"; var result = sutProvider.Sut.TokenValid(token); Assert.False(result); } [Theory, BitAutoData] public void TokenValid_FalseIfTokenInvalid(TestTokenable tokenable) { var sutProvider = GetSutProvider(); tokenable.ForceInvalid = true; var token = sutProvider.Sut.Protect(tokenable); var result = sutProvider.Sut.TokenValid(token); Assert.False(result); } [Theory, BitAutoData] public void TryUnprotect_TrueIfSuccess(TestTokenable tokenable) { var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable); var result = sutProvider.Sut.TryUnprotect(token, out var data); Assert.True(result); AssertHelper.AssertPropertyEqual(tokenable, data); } [Theory, BitAutoData] public void TokenValid_TrueIfSuccess(TestTokenable tokenable) { tokenable.ForceInvalid = false; var sutProvider = GetSutProvider(); var token = sutProvider.Sut.Protect(tokenable); var result = sutProvider.Sut.TokenValid(token); Assert.True(result); } }