Skip to content

Commit

Permalink
Added audience validation test
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddesmet committed May 24, 2022
1 parent 57a4456 commit a1a97a6
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 142 deletions.
2 changes: 1 addition & 1 deletion src/Paseto/Validators/EqualValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <summary>
/// The Equality Validator. This class cannot be inherited.
/// </summary>
/// <seealso cref="Paseto.Validation.BaseValidator" />
/// <seealso cref="Paseto.Validators.BaseValidator" />
public sealed class EqualValidator : BaseValidator
{
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Paseto/Validators/ExpirationTimeValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <summary>
/// The ExpirationTime Validator. This class cannot be inherited.
/// </summary>
/// <seealso cref="Paseto.Validation.BaseValidator" />
/// <seealso cref="Paseto.Validators.BaseValidator" />
public sealed class ExpirationTimeValidator : BaseValidator
{
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Paseto/Validators/IssuedAtValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <summary>
/// The NotAfter Validator. This class cannot be inherited.
/// </summary>
/// <seealso cref="Paseto.Validation.BaseValidator" />
/// <seealso cref="Paseto.Validators.BaseValidator" />
public sealed class IssuedAtValidator : BaseValidator
{
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Paseto/Validators/NotBeforeValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// <summary>
/// The NotBefore Validator. This class cannot be inherited.
/// </summary>
/// <seealso cref="Paseto.Validation.BaseValidator" />
/// <seealso cref="Paseto.Validators.BaseValidator" />
public sealed class NotBeforeValidator : BaseValidator
{
/// <summary>
Expand Down
1 change: 0 additions & 1 deletion tests/Paseto.Tests/PasetoBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,6 @@ public void ShouldFailOnLocalDecodeWhenTokenFooterIsInvalid(ProtocolVersion vers
}

// TODO: Public Decode fails tests, include invalid header v1.remote.
// TODO: Decode with payload validation (success and fails)

[Theory(DisplayName = "Should fail on Local Decode when Token's Footer is not valid")]
[InlineData(ProtocolVersion.V1, "v1.local.4VyfcVcFAOAbB8yEM1j1Ob7Iez5VZJy5kHNsQxmlrAwKUbOtq9cv39T2fC0MDWafX0nQJ4grFZzTdroMvU772RW-X1oTtoFBjsl_3YYHWnwgqzs0aFc3ejjORmKP4KUM339W3szA28OabR192eRqiyspQ6xPM35NMR-04-FhRJZEWiF0W5oWjPVtGPjeVjm2DI4YtJg.eyJraWQiOiJVYmtLOFk2aXY0R1poRnA2VHgzSVdMV0xmTlhTRXZKY2RUM3pkUjY1WVp4byJ9", "{\"kid\":\"UbkK8Y6iv4GZhFp6Tx3IWLWLfNXSEvJcdT3zdR65YZxo\"}")]
Expand Down
333 changes: 196 additions & 137 deletions tests/Paseto.Tests/PasetoValidationTest.cs
Original file line number Diff line number Diff line change
@@ -1,138 +1,197 @@
using System;
using System.ComponentModel;
using System.Linq;
using FluentAssertions;
using Paseto.Builder;
using Paseto.Cryptography.Key;
using Xunit;

namespace Paseto.Tests
{
public sealed class PasetoValidationTest
{
[Theory(DisplayName = "Should succeed on token with valid issuer")]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithValidIssuerValidationSucceeds(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = "valid-issuer",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Issuer, "valid-issuer");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeTrue();
}

[Theory(DisplayName = "Should fail on token with invalid issuer")]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithInValidIssuerValidationFails(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = "valid-issuer",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Issuer, "invalid-issuer");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeFalse();
}

[Theory(DisplayName = "Should succeed on token with valid subject")]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithValidSubjectValidationSucceeds(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateSubject = true,
ValidSubject = "valid-subject",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Subject, "valid-subject");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeTrue();
}

[Theory(DisplayName = "Should fail on token with invalid subject")]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithInValidSubjectValidationFails(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateSubject = true,
ValidSubject = "valid-subject",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Subject, "invalid-subject");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeFalse();
}

private static (string token, PasetoKey decodeKey) GenerateToken(ProtocolVersion version, Purpose purpose, string claimName, string claimValue)
{
var builder = new PasetoBuilder().Use(version, purpose);
switch (claimName)
{
case PasetoRegisteredClaimNames.Issuer:
builder.Issuer(claimValue);
break;
case PasetoRegisteredClaimNames.Subject:
builder.Subject(claimValue);
break;
default:
throw new NotImplementedException();
}
switch (purpose)
{
case Purpose.Local:
{
var key = builder.GenerateSymmetricKey();
var token = builder
.WithKey(key)
.Encode();
return (token, key);
}
case Purpose.Public:
{
var keyPair = builder.GenerateAsymmetricKeyPair(Enumerable.Repeat((byte)0x00, 32).ToArray());
var token = builder
.WithKey(keyPair.SecretKey)
.Encode();
return (token, keyPair.PublicKey);
}
default:
throw new InvalidEnumArgumentException();
}
}
}
namespace Paseto.Tests;

using System;
using System.ComponentModel;
using System.Linq;
using FluentAssertions;
using Paseto.Builder;
using Paseto.Cryptography.Key;
using Xunit;

public sealed class PasetoValidationTest
{
[Theory(DisplayName = "Should succeed on token with valid audience")]
[InlineData(ProtocolVersion.V1, Purpose.Local)]
[InlineData(ProtocolVersion.V1, Purpose.Public)]
[InlineData(ProtocolVersion.V2, Purpose.Local)]
[InlineData(ProtocolVersion.V2, Purpose.Public)]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithValidAudienceValidationSucceeds(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateAudience = true,
ValidAudience = "valid-audience",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Audience, "valid-audience");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeTrue();
}

[Theory(DisplayName = "Should fail on token with invalid audience")]
[InlineData(ProtocolVersion.V1, Purpose.Local)]
[InlineData(ProtocolVersion.V1, Purpose.Public)]
[InlineData(ProtocolVersion.V2, Purpose.Local)]
[InlineData(ProtocolVersion.V2, Purpose.Public)]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithInValidAudienceValidationFails(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateAudience = true,
ValidAudience = "valid-audience",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Audience, "invalid-audience");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeFalse();
}

[Theory(DisplayName = "Should succeed on token with valid issuer")]
[InlineData(ProtocolVersion.V1, Purpose.Local)]
[InlineData(ProtocolVersion.V1, Purpose.Public)]
[InlineData(ProtocolVersion.V2, Purpose.Local)]
[InlineData(ProtocolVersion.V2, Purpose.Public)]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithValidIssuerValidationSucceeds(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = "valid-issuer",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Issuer, "valid-issuer");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeTrue();
}

[Theory(DisplayName = "Should fail on token with invalid issuer")]
[InlineData(ProtocolVersion.V1, Purpose.Local)]
[InlineData(ProtocolVersion.V1, Purpose.Public)]
[InlineData(ProtocolVersion.V2, Purpose.Local)]
[InlineData(ProtocolVersion.V2, Purpose.Public)]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithInValidIssuerValidationFails(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = "valid-issuer",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Issuer, "invalid-issuer");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeFalse();
}

[Theory(DisplayName = "Should succeed on token with valid subject")]
[InlineData(ProtocolVersion.V1, Purpose.Local)]
[InlineData(ProtocolVersion.V1, Purpose.Public)]
[InlineData(ProtocolVersion.V2, Purpose.Local)]
[InlineData(ProtocolVersion.V2, Purpose.Public)]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithValidSubjectValidationSucceeds(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateSubject = true,
ValidSubject = "valid-subject",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Subject, "valid-subject");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeTrue();
}

[Theory(DisplayName = "Should fail on token with invalid subject")]
[InlineData(ProtocolVersion.V1, Purpose.Local)]
[InlineData(ProtocolVersion.V1, Purpose.Public)]
[InlineData(ProtocolVersion.V2, Purpose.Local)]
[InlineData(ProtocolVersion.V2, Purpose.Public)]
[InlineData(ProtocolVersion.V3, Purpose.Local)]
[InlineData(ProtocolVersion.V3, Purpose.Public)]
[InlineData(ProtocolVersion.V4, Purpose.Local)]
[InlineData(ProtocolVersion.V4, Purpose.Public)]
public void TokenWithInValidSubjectValidationFails(ProtocolVersion version, Purpose purpose)
{
var validationParameters = new PasetoTokenValidationParameters()
{
ValidateSubject = true,
ValidSubject = "valid-subject",
};

var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Subject, "invalid-subject");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
.Decode(token, validationParameters);

decoded.IsValid.Should().BeFalse();
}

private static (string token, PasetoKey decodeKey) GenerateToken(ProtocolVersion version, Purpose purpose, string claimName, string claimValue)
{
var builder = new PasetoBuilder()
.Use(version, purpose)
.AddClaim(claimName, claimValue);

switch (purpose)
{
case Purpose.Local:
{
var key = builder.GenerateSymmetricKey();
var token = builder
.WithKey(key)
.Encode();
return (token, key);
}
case Purpose.Public:
{
var keyPair = builder.GenerateAsymmetricKeyPair(Enumerable.Repeat((byte)0x00, 32).ToArray());
var token = builder
.WithKey(keyPair.SecretKey)
.Encode();
return (token, keyPair.PublicKey);
}
default:
throw new InvalidEnumArgumentException();
}
}
}

0 comments on commit a1a97a6

Please sign in to comment.