Ошибка канала-носителя = & quot; invalid_token & quot; из .net core 2.0

У меня установлена ​​система аутентификации на PHP, которую я пытаюсь использовать для отправки веб-токенов JSON в клиентское приложение, чтобы приложение получило доступ к API-интерфейсу .net core 2.0. Таким образом, сервер аутентификации принимает учетные данные пользователя и, если учетные данные проходят, он генерирует токен, используя пару открытого / секретного ключей, которую я создал с помощью openssl. Я генерирую токен, используя процедуру здесь: http://www.phpbuilder.com/articles/application-architecture/security/using-a-json-web-token-in-php.html

Я могу декодировать полученный токен с помощью jwt.io. Декодированная версия выглядит так:

{
"typ": "JWT",
"alg": "HS256"}

{
"iss": "https://crm.advtis.com",
"exp": "2017-12-21 18:14:42",
"aud": "https://localhost:44354",
"data": {
"username": "pwalter@advtis.com",
"role": 1
}
}

Я могу ввести строку из моего файла закрытого ключа, который использовался для кодирования токена, и jwt.io говорит, что подпись действительна.

Итак, теперь я хочу отправить токен вместе с запросом в мой API, чтобы получить доступ к этому ресурсу, который во время отладки находится на localhost. Вот код запуска .NET 2.0, относящийся к этому:

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SmartRxDBContext>();

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Audience = "https://localhost:44354/";
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = "https://crm.advtis.com/",
IssuerSigningKey = new X509SecurityKey(new X509Certificate2("C:\\Path\\To\\webOrders-cert-AspNetPubkey.cert"))
};
});
services.AddMvc();
}

Указанный путь связан с открытым ключом в формате pem, который я сгенерировал, также используя openssl, из закрытого ключа, используемого для кодирования jwt. Я пытался следовать этому примеру для части .NET Core — Проверка и авторизация JWT в ASP.NET Core
— но, конечно, вся конфигурация промежуточного программного обеспечения аутентификации была перемещена в 2.0 в метод ConfigureServices, и больше нет опции AutomaticAuthorization.

Все вроде бы нормально, но я получаю ошибку 401 — Unauthorized Bearer error = «invalid_token» при выполнении запроса с заголовком как Authorization: Bearer TOKEN Во всяком случае, я надеялся, что кто-то может дать мне несколько советов о том, где я могу пойти не так и / или как я могу устранить неполадки в дальнейшем.

0

Решение

Итак, я понял это для всех, кто хочет запустить сценарий такого же типа.

Моя первая проблема заключалась в том, что я использовал HMAC для генерации токенов на стороне PHP. HMAC не является алгоритмом парных / частных пар. Я установил firebase / PHP-JWT библиотека с composer, и использовал это для генерации моего токена следующим образом:

use \Firebase\JWT\JWT;
$token = array(
"iss" => "https://crm.advtis.com",
"exp" => time()+10000,
"aud" => "https://localhost:44354",
"data" => array(
"username" => "pwalter@advtis.com",
"role" => 1
)
);

$jwt = JWT::encode($token, file_get_contents("../path/to/private.key"), 'RS256');

Файл ключа был сгенерирован в командной строке с помощью OpenSSL. Я использовал ту же утилиту для генерации открытого ключа с закрытым ключом. Оба файла в формате PEM.

Следующее, что мне нужно было сделать, это получить открытый ключ в .NET. Самый простой способ, который я нашел — использовать RSACryptoServiceProvider, вроде этого:

private static RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
public void ConfigureServices(IServiceCollection services)
{
JwtHelper.FromXmlString(myRSA, "C:\\Users\\Path\\To\\xmlPubKey.xml");
services.AddDbContext<SmartRxDBContext>();

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = "https://crm.advtis.com",
ValidateAudience = true,
ValidAudience = "https://localhost:44354",
IssuerSigningKey = new RsaSecurityKey(myRSA.ExportParameters(false))
};
});
services.AddMvc();

}

Метод JwtHelper.FromXml () был адаптирован из Вот, потому что в .NET 2.0 нет способа импортировать или устанавливать параметры из XML внутри провайдера RSA, поэтому этот метод анализирует XML и устанавливает параметры следующим образом:

public static void FromXml(this RSA rsa, string filepath)
{
RSAParameters parameters = new RSAParameters();

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filepath);

if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
{
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
switch (node.Name)
{
case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
}
}
}
else
{
throw new Exception("Invalid XML RSA key.");
}

rsa.ImportParameters(parameters);
}

Так что в этом суть. Теперь я могу выдавать JWT с моего PHP-сервера на клиентское приложение. Затем я могу отправить JWT в мой .NET Core 2.0 API, чтобы получить доступ к конечным точкам, защищенным атрибутом [Authorize].

0

Другие решения

Других решений пока нет …