Compare commits
7 Commits
8f722ce3c9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| bdf68b6bc4 | |||
| c69635fc43 | |||
| 98fbbea5c3 | |||
| f455241af1 | |||
| 2551de233f | |||
| 25387238e3 | |||
| 2c78ed106c |
66
DigitalData.Auth.Claims/CookieNames.cs
Normal file
66
DigitalData.Auth.Claims/CookieNames.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
namespace DigitalData.Auth.Claims
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides helpers for building cookie names used in the DigitalData.Auth ecosystem.
|
||||||
|
/// </summary>
|
||||||
|
public static class CookieNames
|
||||||
|
{
|
||||||
|
private const string ReceiverSuffix = "SignFLOWReceiver.";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds the cookie name for an envelope receiver token.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="defaultCookieName">The base cookie name configured in <c>AuthApiParams</c>.</param>
|
||||||
|
/// <param name="key">The unique envelope receiver key.</param>
|
||||||
|
/// <returns>A cookie name in the format <c>{defaultCookieName}SignFLOWReceiver.{key}</c>.</returns>
|
||||||
|
public static string GetEnvelopeReceiverCookieName(string defaultCookieName, string key)
|
||||||
|
=> defaultCookieName + ReceiverSuffix + key;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds the cookie name for an envelope receiver token.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique envelope receiver key.</param>
|
||||||
|
/// <returns>A cookie name in the format <c>{defaultCookieName}SignFLOWReceiver.{key}</c>.</returns>
|
||||||
|
public static string GetEnvelopeReceiverCookieName(string key)
|
||||||
|
=> "AuthToken" + ReceiverSuffix + key;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extracts the envelope receiver key from a cookie name, or returns <see langword="null"/> if the cookie name does not match the expected format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cookieName">The full cookie name in the format <c>{defaultCookieName}SignFLOWReceiver.{key}</c>.</param>
|
||||||
|
/// <param name="defaultCookieName">The base cookie name configured in <c>AuthApiParams</c>.</param>
|
||||||
|
/// <returns>The envelope receiver key, or <see langword="null"/> if the cookie name does not match the expected format.</returns>
|
||||||
|
public static string? GetEnvelopeKeyOrDefault(string cookieName, string defaultCookieName = "AuthToken")
|
||||||
|
{
|
||||||
|
var prefix = defaultCookieName + ReceiverSuffix;
|
||||||
|
return cookieName.StartsWith(prefix, StringComparison.Ordinal)
|
||||||
|
? cookieName[prefix.Length..]
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to extract the envelope key from a cookie name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cookieName">The full cookie name in the format <c>{defaultCookieName}SignFLOWReceiver.{key}</c>.</param>
|
||||||
|
/// <param name="defaultCookieName">The base cookie name configured in <c>AuthApiParams</c>.</param>
|
||||||
|
/// <param name="key">The extracted envelope key if the cookie name matches the expected format; otherwise <see langword="null"/>.</param>
|
||||||
|
/// <returns><see langword="true"/> if the key was successfully extracted; otherwise <see langword="false"/>.</returns>
|
||||||
|
public static bool TryGetEnvelopeKey(string cookieName, string defaultCookieName, out string? key)
|
||||||
|
{
|
||||||
|
key = GetEnvelopeKeyOrDefault(cookieName, defaultCookieName);
|
||||||
|
return key is not null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to extract the envelope key from a cookie name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cookieName">The full cookie name in the format <c>{defaultCookieName}SignFLOWReceiver.{key}</c>.</param>
|
||||||
|
/// <param name="key">The extracted envelope key if the cookie name matches the expected format; otherwise <see langword="null"/>.</param>
|
||||||
|
/// <returns><see langword="true"/> if the key was successfully extracted; otherwise <see langword="false"/>.</returns>
|
||||||
|
public static bool TryGetEnvelopeKey(string cookieName, out string? key)
|
||||||
|
{
|
||||||
|
key = GetEnvelopeKeyOrDefault(cookieName, "AuthToken");
|
||||||
|
return key is not null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
<RepositoryUrl>https://git.dd/AppStd/DigitalData.Auth</RepositoryUrl>
|
<RepositoryUrl>https://git.dd/AppStd/DigitalData.Auth</RepositoryUrl>
|
||||||
<PackageTags>digital data auth claims jwt constants</PackageTags>
|
<PackageTags>digital data auth claims jwt constants</PackageTags>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.2</Version>
|
||||||
<AssemblyVersion>1.0.0</AssemblyVersion>
|
<AssemblyVersion>1.0.2</AssemblyVersion>
|
||||||
<FileVersion>1.0.0</FileVersion>
|
<FileVersion>1.0.2</FileVersion>
|
||||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
180
DigitalData.Auth.Tests/Claims/CookieNamesTests.cs
Normal file
180
DigitalData.Auth.Tests/Claims/CookieNamesTests.cs
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
using DigitalData.Auth.Claims;
|
||||||
|
|
||||||
|
namespace DigitalData.Auth.Tests.Claims;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class CookieNamesTests
|
||||||
|
{
|
||||||
|
private const string DefaultCookieName = "AuthToken";
|
||||||
|
private const string Key = "NTE3YmI5YzUtNjA4Mi00ZTYxLWFhYTUtOTg0NjM4";
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetEnvelopeReceiverCookieName_ShouldReturnCorrectFormat()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = $"{DefaultCookieName}SignFLOWReceiver.{Key}";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = CookieNames.GetEnvelopeReceiverCookieName(DefaultCookieName, Key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetEnvelopeReceiverCookieName_WithKeyOnly_ShouldUseDefaultCookieName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = $"{DefaultCookieName}SignFLOWReceiver.{Key}";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = CookieNames.GetEnvelopeReceiverCookieName(Key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetEnvelopeKeyOrDefault_ShouldReturnKey_WhenCookieNameIsValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(DefaultCookieName, Key);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = CookieNames.GetEnvelopeKeyOrDefault(cookieName, DefaultCookieName);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.EqualTo(Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetEnvelopeKeyOrDefault_WithDefaultParam_ShouldReturnKey_WhenCookieUsesDefaultBase()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(Key); // uses "AuthToken" base
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = CookieNames.GetEnvelopeKeyOrDefault(cookieName); // defaultCookieName = "AuthToken"
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.EqualTo(Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetEnvelopeKeyOrDefault_ShouldReturnNull_WhenCookieNameHasWrongBase()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName("OtherCookie", Key);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = CookieNames.GetEnvelopeKeyOrDefault(cookieName, DefaultCookieName);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetEnvelopeKeyOrDefault_ShouldReturnNull_WhenCookieNameIsUnrelated()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var result = CookieNames.GetEnvelopeKeyOrDefault("SomeOtherCookie", DefaultCookieName);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryGetEnvelopeKey_WithDefaultCookieName_ShouldReturnTrueAndKey_WhenCookieNameIsValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(Key); // uses "AuthToken" base
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var success = CookieNames.TryGetEnvelopeKey(cookieName, out var key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(success, Is.True);
|
||||||
|
Assert.That(key, Is.EqualTo(Key));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryGetEnvelopeKey_WithDefaultCookieName_ShouldReturnFalse_WhenCookieNameHasWrongBase()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName("OtherCookie", Key);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var success = CookieNames.TryGetEnvelopeKey(cookieName, out var key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(success, Is.False);
|
||||||
|
Assert.That(key, Is.Null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryGetEnvelopeKey_ShouldReturnTrueAndKey_WhenCookieNameIsValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(DefaultCookieName, Key);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var success = CookieNames.TryGetEnvelopeKey(cookieName, DefaultCookieName, out var key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(success, Is.True);
|
||||||
|
Assert.That(key, Is.EqualTo(Key));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryGetEnvelopeKey_ShouldReturnFalse_WhenCookieNameHasWrongBase()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName("OtherCookie", Key);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var success = CookieNames.TryGetEnvelopeKey(cookieName, DefaultCookieName, out var key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(success, Is.False);
|
||||||
|
Assert.That(key, Is.Null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryGetEnvelopeKey_ShouldReturnFalse_WhenCookieNameIsUnrelated()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var success = CookieNames.TryGetEnvelopeKey("SomeOtherCookie", DefaultCookieName, out var key);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(success, Is.False);
|
||||||
|
Assert.That(key, Is.Null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetAndGetOrDefault_ShouldBeInverse_RoundTrip()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var cookieName = CookieNames.GetEnvelopeReceiverCookieName(DefaultCookieName, Key);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var extractedKey = CookieNames.GetEnvelopeKeyOrDefault(cookieName, DefaultCookieName);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(extractedKey, Is.EqualTo(Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DigitalData.Auth.Claims\DigitalData.Auth.Claims.csproj" />
|
||||||
<ProjectReference Include="..\DigitalData.Auth.Client\DigitalData.Auth.Client.csproj" />
|
<ProjectReference Include="..\DigitalData.Auth.Client\DigitalData.Auth.Client.csproj" />
|
||||||
<ProjectReference Include="..\src\DigitalData.Auth.API\DigitalData.Auth.API.csproj" />
|
<ProjectReference Include="..\src\DigitalData.Auth.API\DigitalData.Auth.API.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using DigitalData.Auth.API.Entities;
|
using DigitalData.Auth.API.Entities;
|
||||||
using DigitalData.Auth.API.Models;
|
using DigitalData.Auth.API.Models;
|
||||||
using DigitalData.Auth.API.Services.Contracts;
|
using DigitalData.Auth.API.Services.Contracts;
|
||||||
|
using DigitalData.Auth.Claims;
|
||||||
using DigitalData.Core.Abstraction.Application;
|
using DigitalData.Core.Abstraction.Application;
|
||||||
using DigitalData.Core.Abstraction.Application.DTO;
|
using DigitalData.Core.Abstraction.Application.DTO;
|
||||||
using DigitalData.Core.Abstractions.Security.Extensions;
|
using DigitalData.Core.Abstractions.Security.Extensions;
|
||||||
@@ -258,7 +259,7 @@ namespace DigitalData.Auth.API.Controllers
|
|||||||
if (cookie)
|
if (cookie)
|
||||||
{
|
{
|
||||||
var cookieOptions = consumer.CookieOptions ?? _apiParams.DefaultCookieOptions;
|
var cookieOptions = consumer.CookieOptions ?? _apiParams.DefaultCookieOptions;
|
||||||
Response.Cookies.Append(_apiParams.DefaultCookieName, token, cookieOptions.Create(lifetime: descriptor.Lifetime));
|
Response.Cookies.Append(CookieNames.GetEnvelopeReceiverCookieName(_apiParams.DefaultCookieName, key), token, cookieOptions.Create(lifetime: descriptor.Lifetime));
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Version>1.4.0</Version>
|
<Version>1.4.1</Version>
|
||||||
<AssemblyVersion>1.4.0</AssemblyVersion>
|
<AssemblyVersion>1.4.1</AssemblyVersion>
|
||||||
<FileVersion>1.4.0</FileVersion>
|
<FileVersion>1.4.1</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user