Browse Source

Improve custom claims.

pull/971/head
Sebastian 4 years ago
parent
commit
1cb314abf2
  1. 4
      backend/src/Squidex.Domain.Users/UserManagerExtensions.cs
  2. 4
      backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs
  3. 39
      backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs
  4. 90
      backend/tests/Squidex.Domain.Users.Tests/SquidexClaimExtensionsTests.cs

4
backend/src/Squidex.Domain.Users/UserManagerExtensions.cs

@ -117,11 +117,11 @@ internal static class UserManagerExtensions
if (values.Properties != null) if (values.Properties != null)
{ {
RemoveClaims(x => x.Type.StartsWith(SquidexClaimTypes.CustomPrefix, StringComparison.OrdinalIgnoreCase)); RemoveClaims(x => x.Type.StartsWith(SquidexClaimTypes.Custom, StringComparison.OrdinalIgnoreCase));
foreach (var (name, value) in values.Properties) foreach (var (name, value) in values.Properties)
{ {
AddClaim($"{SquidexClaimTypes.CustomPrefix}:{name}", value); AddClaim(SquidexClaimTypes.Custom, $"{name}={value}");
} }
} }

4
backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs

@ -15,7 +15,7 @@ namespace Squidex.Shared.Identity
public const string ConsentForEmails = "urn:squidex:consent:emails"; public const string ConsentForEmails = "urn:squidex:consent:emails";
public const string CustomPrefix = "urn:squidex:custom"; public const string Custom = "urn:squidex:custom";
public const string DisplayName = "urn:squidex:name"; public const string DisplayName = "urn:squidex:name";
@ -33,6 +33,6 @@ namespace Squidex.Shared.Identity
public const string TotalApps = "urn:squidex:internal:totalApps"; public const string TotalApps = "urn:squidex:internal:totalApps";
public const string UIPrefix = "urn:squidex:custom"; public const string UIProperty = "urn:squidex:ui";
} }
} }

39
backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs

@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Text.RegularExpressions;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
namespace Squidex.Shared.Identity namespace Squidex.Shared.Identity
@ -18,6 +19,9 @@ namespace Squidex.Shared.Identity
{ {
private const string ClientPrefix = "client_"; private const string ClientPrefix = "client_";
private static readonly Regex KeyValueAppClaim = new Regex("(?<App>[\\S]+),(?<Key>[^=]+)=(?<Value>.+)", RegexOptions.Compiled);
private static readonly Regex KeyValueClaim = new Regex("(?<Key>[^=]+)=(?<Value>.+)", RegexOptions.Compiled);
public static PermissionSet Permissions(this IEnumerable<Claim> user) public static PermissionSet Permissions(this IEnumerable<Claim> user)
{ {
var permissions = user.GetClaims(SquidexClaimTypes.Permissions).Select(x => x.Value); var permissions = user.GetClaims(SquidexClaimTypes.Permissions).Select(x => x.Value);
@ -106,7 +110,7 @@ namespace Squidex.Shared.Identity
public static IEnumerable<(string Name, string Value)> GetCustomProperties(this IEnumerable<Claim> user) public static IEnumerable<(string Name, string Value)> GetCustomProperties(this IEnumerable<Claim> user)
{ {
var prefix = SquidexClaimTypes.CustomPrefix; var prefix = $"{SquidexClaimTypes.Custom}:";
foreach (var claim in user) foreach (var claim in user)
{ {
@ -114,16 +118,25 @@ namespace Squidex.Shared.Identity
if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{ {
var name = type[(prefix.Length + 1)..].ToString(); var name = type[prefix.Length..].ToString();
yield return (name.Trim(), claim.Value.Trim());
}
else if (type.Equals(SquidexClaimTypes.Custom, StringComparison.OrdinalIgnoreCase))
{
var match = KeyValueClaim.Match(claim.Value);
yield return (name, claim.Value); if (match.Success)
{
yield return (match.Groups["Key"].Value.Trim(), match.Groups["Value"].Value.Trim());
}
} }
} }
} }
public static IEnumerable<(string Name, string Value)> GetUIProperties(this IEnumerable<Claim> user, string app) public static IEnumerable<(string Name, string Value)> GetUIProperties(this IEnumerable<Claim> user, string app)
{ {
var prefix = $"{SquidexClaimTypes.UIPrefix}:{app}"; var prefix = $"{SquidexClaimTypes.UIProperty}:{app}:";
foreach (var claim in user) foreach (var claim in user)
{ {
@ -131,9 +144,23 @@ namespace Squidex.Shared.Identity
if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{ {
var name = type[(prefix.Length + 1)..].ToString(); var name = type[prefix.Length..].ToString();
yield return (name.Trim(), claim.Value.Trim());
}
else if (type.Equals(SquidexClaimTypes.UIProperty, StringComparison.OrdinalIgnoreCase))
{
if (!claim.Value.StartsWith(app, StringComparison.OrdinalIgnoreCase))
{
continue;
}
var match = KeyValueAppClaim.Match(claim.Value);
yield return (name, claim.Value); if (match.Success)
{
yield return (match.Groups["Key"].Value.Trim(), match.Groups["Value"].Value.Trim());
}
} }
} }
} }

90
backend/tests/Squidex.Domain.Users.Tests/SquidexClaimExtensionsTests.cs

@ -0,0 +1,90 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Security.Claims;
using Squidex.Shared.Identity;
namespace Squidex.Domain.Users;
public class SquidexClaimExtensionsTests
{
[Fact]
public void Should_extract_custom_claims_v1()
{
var source = new[]
{
new Claim($"{SquidexClaimTypes.Custom}:key1", "value1"),
new Claim($"{SquidexClaimTypes.Custom}:key2", "value2 "),
};
var result = source.GetCustomProperties();
Assert.Equal(new[]
{
("key1", "value1"),
("key2", "value2")
}, result.ToArray());
}
[Fact]
public void Should_extract_custom_claims_v2()
{
var source = new[]
{
new Claim(SquidexClaimTypes.Custom, "key1=value1"),
new Claim(SquidexClaimTypes.Custom, "key2=value2 "),
new Claim(SquidexClaimTypes.Custom, "value "),
};
var result = source.GetCustomProperties();
Assert.Equal(new[]
{
("key1", "value1"),
("key2", "value2")
}, result.ToArray());
}
[Fact]
public void Should_extract_ui_claims_v1()
{
var source = new[]
{
new Claim($"{SquidexClaimTypes.UIProperty}:app1:key1", "value1"),
new Claim($"{SquidexClaimTypes.UIProperty}:app1:key2", "value2 "),
new Claim($"{SquidexClaimTypes.UIProperty}:app2:key3", "value3"),
};
var result = source.GetUIProperties("app1");
Assert.Equal(new[]
{
("key1", "value1"),
("key2", "value2")
}, result.ToArray());
}
[Fact]
public void Should_extract_ui_claims_v2()
{
var source = new[]
{
new Claim($"{SquidexClaimTypes.UIProperty}", "app1,value"),
new Claim($"{SquidexClaimTypes.UIProperty}", "app1,key1=value1"),
new Claim($"{SquidexClaimTypes.UIProperty}", "app1,key2=value2 "),
new Claim($"{SquidexClaimTypes.UIProperty}", "app2,key3=value3"),
};
var result = source.GetUIProperties("app1");
Assert.Equal(new[]
{
("key1", "value1"),
("key2", "value2")
}, result.ToArray());
}
}
Loading…
Cancel
Save