Browse Source
- add [TokenWildcardIssuerValidator](https://github.com/maliming/Owl.TokenWildcardIssuerValidator) - The microservice module adds jwt `IssuerValidator`pull/1235/head
23 changed files with 115 additions and 263 deletions
@ -1,112 +0,0 @@ |
|||||
|
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace LY.MicroService.Applications.Single; |
|
||||
|
|
||||
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)] |
|
||||
public class AbpDynamicFeatureDefinitionStoreInMemoryCache : IDynamicFeatureDefinitionStoreInMemoryCache |
|
||||
{ |
|
||||
public string CacheStamp { get; set; } |
|
||||
|
|
||||
protected IDictionary<string, FeatureGroupDefinition> FeatureGroupDefinitions { get; } |
|
||||
protected IDictionary<string, FeatureDefinition> FeatureDefinitions { get; } |
|
||||
protected StringValueTypeSerializer StateCheckerSerializer { get; } |
|
||||
protected ILocalizableStringSerializer LocalizableStringSerializer { get; } |
|
||||
|
|
||||
public SemaphoreSlim SyncSemaphore { get; } = new(1, 1); |
|
||||
|
|
||||
public DateTime? LastCheckTime { get; set; } |
|
||||
|
|
||||
public AbpDynamicFeatureDefinitionStoreInMemoryCache( |
|
||||
StringValueTypeSerializer stateCheckerSerializer, |
|
||||
ILocalizableStringSerializer localizableStringSerializer) |
|
||||
{ |
|
||||
StateCheckerSerializer = stateCheckerSerializer; |
|
||||
LocalizableStringSerializer = localizableStringSerializer; |
|
||||
|
|
||||
FeatureGroupDefinitions = new Dictionary<string, FeatureGroupDefinition>(); |
|
||||
FeatureDefinitions = new Dictionary<string, FeatureDefinition>(); |
|
||||
} |
|
||||
|
|
||||
public Task FillAsync( |
|
||||
List<FeatureGroupDefinitionRecord> featureGroupRecords, |
|
||||
List<FeatureDefinitionRecord> featureRecords) |
|
||||
{ |
|
||||
FeatureGroupDefinitions.Clear(); |
|
||||
FeatureDefinitions.Clear(); |
|
||||
|
|
||||
var context = new FeatureDefinitionContext(); |
|
||||
|
|
||||
foreach (var featureGroupRecord in featureGroupRecords) |
|
||||
{ |
|
||||
var featureGroup = context.AddGroup( |
|
||||
featureGroupRecord.Name, |
|
||||
featureGroupRecord.DisplayName != null ? LocalizableStringSerializer.Deserialize(featureGroupRecord.DisplayName) : null |
|
||||
); |
|
||||
|
|
||||
FeatureGroupDefinitions[featureGroup.Name] = featureGroup; |
|
||||
|
|
||||
foreach (var property in featureGroupRecord.ExtraProperties) |
|
||||
{ |
|
||||
featureGroup[property.Key] = property.Value; |
|
||||
} |
|
||||
|
|
||||
var featureRecordsInThisGroup = featureRecords |
|
||||
.Where(p => p.GroupName == featureGroup.Name); |
|
||||
|
|
||||
foreach (var featureRecord in featureRecordsInThisGroup.Where(x => x.ParentName == null)) |
|
||||
{ |
|
||||
AddFeatureRecursively(featureGroup, featureRecord, featureRecords); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
|
|
||||
public FeatureDefinition GetFeatureOrNull(string name) |
|
||||
{ |
|
||||
return FeatureDefinitions.GetOrDefault(name); |
|
||||
} |
|
||||
|
|
||||
public IReadOnlyList<FeatureDefinition> GetFeatures() |
|
||||
{ |
|
||||
return FeatureDefinitions.Values.ToList(); |
|
||||
} |
|
||||
|
|
||||
public IReadOnlyList<FeatureGroupDefinition> GetGroups() |
|
||||
{ |
|
||||
return FeatureGroupDefinitions.Values.ToList(); |
|
||||
} |
|
||||
|
|
||||
private void AddFeatureRecursively(ICanCreateChildFeature featureContainer, |
|
||||
FeatureDefinitionRecord featureRecord, |
|
||||
List<FeatureDefinitionRecord> allFeatureRecords) |
|
||||
{ |
|
||||
var feature = featureContainer.CreateChildFeature( |
|
||||
featureRecord.Name, |
|
||||
featureRecord.DefaultValue, |
|
||||
featureRecord.DisplayName != null ? LocalizableStringSerializer.Deserialize(featureRecord.DisplayName) : null, |
|
||||
featureRecord.Description != null ? LocalizableStringSerializer.Deserialize(featureRecord.Description) : null, |
|
||||
StateCheckerSerializer.Deserialize(featureRecord.ValueType), |
|
||||
featureRecord.IsVisibleToClients, |
|
||||
featureRecord.IsAvailableToHost |
|
||||
); |
|
||||
|
|
||||
FeatureDefinitions[feature.Name] = feature; |
|
||||
|
|
||||
if (!featureRecord.AllowedProviders.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
feature.AllowedProviders.AddRange(featureRecord.AllowedProviders.Split(',')); |
|
||||
} |
|
||||
|
|
||||
foreach (var property in featureRecord.ExtraProperties) |
|
||||
{ |
|
||||
feature[property.Key] = property.Value; |
|
||||
} |
|
||||
|
|
||||
foreach (var subFeature in allFeatureRecords.Where(p => p.ParentName == featureRecord.Name)) |
|
||||
{ |
|
||||
AddFeatureRecursively(feature, subFeature, allFeatureRecords); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,127 +0,0 @@ |
|||||
using Microsoft.IdentityModel.Tokens; |
|
||||
using System.Globalization; |
|
||||
using System.Text; |
|
||||
using Volo.Abp.Text.Formatting; |
|
||||
|
|
||||
namespace LY.MicroService.Applications.Single; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/Validators.cs#L207
|
|
||||
/// </summary>
|
|
||||
public static class TokenWildcardIssuerValidator |
|
||||
{ |
|
||||
private const string IDX10204 = "IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null."; |
|
||||
private const string IDX10205 = "IDX10205: Issuer validation failed. Issuer: '{0}'. Did not match: validationParameters.ValidIssuer: '{1}' or validationParameters.ValidIssuers: '{2}'."; |
|
||||
private const string IDX10211 = "IDX10211: Unable to validate issuer. The 'issuer' parameter is null or whitespace"; |
|
||||
private const string IDX10235 = "IDX10235: ValidateIssuer property on ValidationParameters is set to false. Exiting without validating the issuer."; |
|
||||
private const string IDX10236 = "IDX10236: Issuer Validated.Issuer: '{0}'"; |
|
||||
|
|
||||
public static readonly IssuerValidator IssuerValidator = (issuer, token, validationParameters) => |
|
||||
{ |
|
||||
if (validationParameters == null) |
|
||||
{ |
|
||||
throw LogHelper.LogArgumentNullException(nameof(validationParameters)); |
|
||||
} |
|
||||
|
|
||||
if (!validationParameters.ValidateIssuer) |
|
||||
{ |
|
||||
LogHelper.LogInformation(IDX10235); |
|
||||
return issuer; |
|
||||
} |
|
||||
|
|
||||
if (string.IsNullOrWhiteSpace(issuer)) |
|
||||
{ |
|
||||
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(IDX10211) |
|
||||
{ |
|
||||
InvalidIssuer = issuer |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
// Throw if all possible places to validate against are null or empty
|
|
||||
if (string.IsNullOrWhiteSpace(validationParameters.ValidIssuer) && |
|
||||
validationParameters.ValidIssuers == null) |
|
||||
{ |
|
||||
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(IDX10204) |
|
||||
{ |
|
||||
InvalidIssuer = issuer |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
if (string.Equals(validationParameters.ValidIssuer, issuer, StringComparison.Ordinal)) |
|
||||
{ |
|
||||
LogHelper.LogInformation(IDX10236, issuer); |
|
||||
return issuer; |
|
||||
} |
|
||||
|
|
||||
if (!string.IsNullOrWhiteSpace(validationParameters.ValidIssuer)) |
|
||||
{ |
|
||||
var extractResult = FormattedStringValueExtracter.Extract(issuer, validationParameters.ValidIssuer, ignoreCase: true); |
|
||||
if (extractResult.IsMatch && |
|
||||
extractResult.Matches.Aggregate(validationParameters.ValidIssuer, (current, nameValue) => current.Replace($"{{{nameValue.Name}}}", nameValue.Value)) |
|
||||
.IndexOf(issuer, StringComparison.OrdinalIgnoreCase) >= 0) |
|
||||
{ |
|
||||
return issuer; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (null != validationParameters.ValidIssuers) |
|
||||
{ |
|
||||
foreach (var str in validationParameters.ValidIssuers) |
|
||||
{ |
|
||||
if (string.IsNullOrEmpty(str)) |
|
||||
{ |
|
||||
LogHelper.LogInformation(IDX10235); |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if (string.Equals(str, issuer, StringComparison.Ordinal)) |
|
||||
{ |
|
||||
LogHelper.LogInformation(IDX10236, issuer); |
|
||||
return issuer; |
|
||||
} |
|
||||
|
|
||||
var extractResult = FormattedStringValueExtracter.Extract(issuer, str, ignoreCase: true); |
|
||||
if (extractResult.IsMatch && |
|
||||
extractResult.Matches.Aggregate(str, (current, nameValue) => current.Replace($"{{{nameValue.Name}}}", nameValue.Value)) |
|
||||
.IndexOf(issuer, StringComparison.OrdinalIgnoreCase) >= 0) |
|
||||
{ |
|
||||
return issuer; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
throw LogHelper.LogExceptionMessage( |
|
||||
new SecurityTokenInvalidIssuerException(LogHelper.FormatInvariant(IDX10205, issuer, |
|
||||
(validationParameters.ValidIssuer ?? "null"), |
|
||||
SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers))) |
|
||||
{ |
|
||||
InvalidIssuer = issuer |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
private static string SerializeAsSingleCommaDelimitedString(IEnumerable<string> strings) |
|
||||
{ |
|
||||
if (strings == null) |
|
||||
{ |
|
||||
return Utility.Null; |
|
||||
} |
|
||||
|
|
||||
var sb = new StringBuilder(); |
|
||||
var first = true; |
|
||||
foreach (var str in strings) |
|
||||
{ |
|
||||
if (first) |
|
||||
{ |
|
||||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", str ?? Utility.Null); |
|
||||
first = false; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
sb.AppendFormat(CultureInfo.InvariantCulture, ", {0}", str ?? Utility.Null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return first ? Utility.Empty : sb.ToString(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@ -1,9 +1,9 @@ |
|||||
{ |
{ |
||||
"version": "9.1.3", |
"version": "9.2.0", |
||||
"name": "my-app-authserver", |
"name": "my-app-authserver", |
||||
"private": true, |
"private": true, |
||||
"dependencies": { |
"dependencies": { |
||||
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.1.3", |
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.2.0", |
||||
"@abp/qrcode": "9.1.3" |
"@abp/qrcode": "9.2.0" |
||||
} |
} |
||||
} |
} |
||||
Loading…
Reference in new issue