Skip to content

Commit

Permalink
Added subject validation
Browse files Browse the repository at this point in the history
  • Loading branch information
lyra95 authored May 11, 2022
1 parent 375d3c1 commit eff6bd6
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
10 changes: 10 additions & 0 deletions src/Paseto/Handlers/PasetoPurposeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public virtual PasetoTokenValidationResult ValidateTokenPayload(PasetoToken toke
ValidateLifetime(token, validationParameters);
ValidateAudience(token, validationParameters);
ValidateIssuer(token, validationParameters);
ValidateSubject(token, validationParameters);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -87,4 +88,13 @@ protected virtual void ValidateIssuer(PasetoToken token, PasetoTokenValidationPa
if (token.Payload.HasIssuer())
new EqualValidator(token.Payload, PasetoRegisteredClaimNames.Issuer).Validate(validationParameters.ValidIssuer);
}

protected virtual void ValidateSubject(PasetoToken token, PasetoTokenValidationParameters validationParameters)
{
if (!validationParameters.ValidateSubject && !string.IsNullOrWhiteSpace(validationParameters.ValidSubject))
return;

if (token.Payload.HasSubject())
new EqualValidator(token.Payload, PasetoRegisteredClaimNames.Subject).Validate(validationParameters.ValidSubject);
}
}
10 changes: 10 additions & 0 deletions src/Paseto/PasetoTokenValidationParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public class PasetoTokenValidationParameters
/// </summary>
public bool ValidateIssuer { get; set; }

/// <summary>
/// Gets or sets a value for comparing the subject of the payload.
/// </summary>
public bool ValidateSubject { get; set; }

/// <summary>
/// Gets or sets the valid audience for comparing against the payload-provided aud.
/// </summary>
Expand All @@ -31,4 +36,9 @@ public class PasetoTokenValidationParameters
/// Gets or sets the valid issuer for comparing against the payload-provided iss.
/// </summary>
public string ValidIssuer { get; set; }

/// <summary>
/// Gets or sets the valid subject for comparing against the payload-provided sub.
/// </summary>
public string ValidSubject { get; set; }
}
66 changes: 60 additions & 6 deletions tests/Paseto.Tests/PasetoValidationTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.ComponentModel;
using System;
using System.ComponentModel;
using System.Linq;
using FluentAssertions;
using Paseto.Builder;
Expand All @@ -22,7 +23,7 @@ public void TokenWithValidIssuerValidationSucceeds(ProtocolVersion version, Purp
ValidIssuer = "valid-issuer",
};

var (token, decodeKey) = GenerateToken(version, purpose, "valid-issuer");
var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Issuer, "valid-issuer");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
Expand All @@ -44,7 +45,7 @@ public void TokenWithInValidIssuerValidationFails(ProtocolVersion version, Purpo
ValidIssuer = "valid-issuer",
};

var (token, decodeKey) = GenerateToken(version, purpose, "invalid-issuer");
var (token, decodeKey) = GenerateToken(version, purpose, PasetoRegisteredClaimNames.Issuer, "invalid-issuer");
var decoded = new PasetoBuilder()
.Use(version, purpose)
.WithKey(decodeKey)
Expand All @@ -53,17 +54,71 @@ public void TokenWithInValidIssuerValidationFails(ProtocolVersion version, Purpo
decoded.IsValid.Should().BeFalse();
}

private static (string token, PasetoKey decodeKey) GenerateToken(ProtocolVersion version, Purpose purpose, string issuer)
[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)
.Issuer(issuer)
.Encode();
return (token, key);
}
Expand All @@ -72,7 +127,6 @@ private static (string token, PasetoKey decodeKey) GenerateToken(ProtocolVersion
var keyPair = builder.GenerateAsymmetricKeyPair(Enumerable.Repeat((byte)0x00, 32).ToArray());
var token = builder
.WithKey(keyPair.SecretKey)
.Issuer(issuer)
.Encode();
return (token, keyPair.PublicKey);
}
Expand Down

0 comments on commit eff6bd6

Please sign in to comment.