Skip to content

Instantly share code, notes, and snippets.

@maliming
Created February 20, 2021 06:39
Show Gist options
  • Save maliming/37193c20c2bea4c4779164d95b42d8f7 to your computer and use it in GitHub Desktop.
Save maliming/37193c20c2bea4c4779164d95b42d8f7 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Volo.Abp.Text.Formatting;
using LogHelper = Microsoft.IdentityModel.Logging.LogHelper;
namespace MyCompanyName.MyProjectName
{
/// <summary>
/// https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/Validators.cs#L207
/// </summary>
public static class AbpIssuerValidator
{
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 (!validationParameters.ValidIssuer.IsNullOrWhiteSpace())
{
var extractResult = FormattedStringValueExtracter.Extract(issuer, validationParameters.ValidIssuer, ignoreCase: true);
if (extractResult.IsMatch)
{
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)
{
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();
}
}
}
@maliming
Copy link
Author

private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
    context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://www.api.abp.io";
            options.Audience = "abp_io";

            options.TokenValidationParameters.IssuerValidator = AbpIssuerValidator.IssuerValidator;
            options.TokenValidationParameters.ValidIssuers = new[]
            {
                "https://{0}.api.abp.io"
            };
        });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment