ASP. NET Ядро: Как проверить JWT без доступа к Интернету - PullRequest
0 голосов
/ 02 февраля 2020

Итак, вот как я проверяю токен-носитель JWT в бэкэнде:

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.Authority = $"https://{Configuration["Auth0:Authority"]}";
                options.Audience = Configuration["Auth0:Audience"];
            });

Он работает нормально, так как Net ядро ​​консультируется с полномочиями для получения необходимой информации (например, ключа подписи) под капот. В моем случае он общается с серверами Auth0 через https: // <МОЙ АРЕНДАТОР> .auth0.com / .well-known / openid-configuration.

Проблема заключается в том, что мое приложение не может связаться с сервером Auth0, когда я разверните его в Intr anet, который не имеет доступа к inte rnet. Вот ошибка, которую я получаю:

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://< My TENANT >.auth0.com/.well-known/openid-configuration'.

Я пытался ввести ключ RSA вручную, но не удача и та же ошибка:

AddJwtBearer(options =>
            {
                options.Authority = $"https://{Configuration["Auth0:Domain"]}";
                options.Audience = Configuration["Auth0:Audience"];
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateLifetime = true,
                    RequireSignedTokens = true,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = GetRsaKey(),
                };
            }); 

 private SecurityKey GetRsaKey()
        {
            byte[] modulus = Decode("r5cpJ....-fUGjJCH1QQ");
            byte[] exponent = Decode("A...AB");

            var rsaParameters = new RSAParameters
            {
                Modulus = modulus,
                Exponent = exponent
            };

            using var rsaProvider = new RSACryptoServiceProvider();
            rsaProvider.ImportParameters(rsaParameters);
            return new RsaSecurityKey(rsaProvider);
        }

Любой обходной путь?

Ответы [ 3 ]

1 голос
/ 03 февраля 2020

TokenValidationParameters можно использовать в сценарии, в котором вы хотите проверить токены без доступа к серверу выдачи. Тогда вы не сможете установить Authority, установить ValidateIssuerSigningKey и ValidateIssuer и, наконец, установить IssuerSigningKey, который является ключом publi c, используемым для проверки входящих токенов JWT. Здесь и здесь - примеры кода.

Но проблема в том, что вы не можете общаться с Auth0, это означает, что вы не можете получить последний открытый ключ для проверки токена, выданного Auth0, вы должны подтвердить, что ваш локальный публичный ключ c syn c с новейшими изданиями Auth0. Если аутентификация также контролируется вами, вы можете рассмотреть возможность использования Identity Server4 , который является локальной платформой аутентификации / SSO, или вы можете реализовать аутентификацию JWT, как показано здесь .

1 голос
/ 03 февраля 2020

Ответ от Nan Yu очень точный, и у вас есть следующие высокоуровневые опции:

  • Сконфигурируйте фиксированный ключ и проверьте токены с ним на заднем конце. Это будет работать некоторое время, но в будущем может привести к серьезным сбоям, если ключи не будут надежно синхронизированы, а Auth0 обновит ключи подписи токена, что может привести к серьезным проблемам для вашей компании.

  • Убедитесь, что ваш бэкэнд имеет исходящее соединение с Auth0, как надежный поставщик, чтобы система могла надежно работать самым простым и стандартным способом.

Это похоже на людей и процесс проблема, а не техническая. Я бы не стал пытаться решить эту проблему путем изменения кода.

Я подозреваю, что ИТ-администраторы пытаются применить устаревшую политику no inte rnet, которая противоречит интересам вашей компании. На уровне ИТ легко внести в белый список только URL-адреса Auth0 и заблокировать другие.

В качестве следующего шага я постараюсь убедить ваших заинтересованных лиц / боссов поддержать стандартную настройку - возможно, переслать им этот пост.

1 голос
/ 02 февраля 2020

Поскольку вы do not have access to the internet, вам необходимо иметь локальную идентификацию и контроль доступа, например Identity Server, или создать собственный JWT Issuer/Validator следующим образом:

  1. Получить закрытый ключ.
  2. Когда пользователь входит в систему, генерирует токен безопасности JWT:
private JwtSecurityToken GetJwtSecurityToken(List<Claim> user_claims)
{
     string privateKey = "YOUR_PRIVATE_KEY";
     var symmetricKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(privateKey));
     var credentials = new SigningCredentials(symmetricKey, SecurityAlgorithms.HmacSha256);

     return new JwtSecurityToken
     (
          issuer: "ISSUER_NAME",
          audience: "AUDIENCE",
          claims: user_claims,
          signingCredentials: credentials
     );
}
Сериализация JWT (из шага 2):
var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);

Отправьте токен пользователю или добавьте его в куки.

В вашем startup file:

services.AddAuthentication()
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, config =>
    {
        config.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "ISSUER",
            ValidAudience = "AUDIENCE",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YOUR_PRIVATE_KEY"))
         };
});
Защитите свои контроллеры, добавив:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Вот и все. И, надеюсь, кто-то скажет нам, если есть какое-либо лучшее решение.


Обновление 1 (добавление ссылки):

Проверьте эту статью Защита ASP. NET Приложения Core 2.0 с JWT .

...