Azure KeyVault - подписать токен JWT - PullRequest
1 голос
/ 08 июля 2019

Я начал использовать Azure Keyvault для хранения закрытых ключей для своего приложения.

У меня есть случай, когда мне нужно подписать токен JWT с помощью закрытого ключа RSA.

Когда у меня был личный ключ в памяти приложения, это было легко, Я бы просто сделал это

var token = new JwtSecurityToken(
                issuer,
                ...,
                claims,
                ...,
                ...,
                signingCredentials_PrivateKey);

Теперь, когда я начал использовать Azure Keyvault, я хочу посмотреть, можно ли подписывать токены JWT с помощью метода KeyVaultClient.SignAsync.

Что-то вроде

KeyVaultClient client = ...;
var token = new JwtSecurityToken(
                issuer,
                ...,
                claims,
                ...,
                ...);
var tokenString = client.SignAsync(myKeyIdentifier, token);

Ответы [ 2 ]

2 голосов
/ 08 июля 2019

В итоге я воспользовался ответом Джека Цзя

var token = new JwtSecurityToken(
                issuer,
                appId,
                claims,
                signDate,
                expiryDate);

var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
    { JwtHeaderParameterNames.Alg, "RS256" },
    { JwtHeaderParameterNames.Kid, "https://myvault.vault.azure.net/keys/mykey/keyid" },
    { JwtHeaderParameterNames.Typ, "JWT" }
}));
var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await _keyVault.SignAsync("https://myvault.vault.azure.net/keys/mykey/keyid", "RS256", digest);

return $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";

Я нашел другое решение, которое мне не очень понравилось, но оно лучше "интегрируется" с библиотеками JWT.

var token = new JwtSecurityToken(
    issuer,
    appId,
    claims,
    signDate,
    expiryDate,
    new SigningCredentials(new KeyVaultSecurityKey("https://myvault.vault.azure.net/keys/mykey/keyid", new KeyVaultSecurityKey.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)), "RS256")
    {
        CryptoProviderFactory = new CryptoProviderFactory() { CustomCryptoProvider = new KeyVaultCryptoProvider() }
    });

var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(token);

Оказывается, есть библиотека Microsoft.IdentityModel.KeyVaultExtensions с расширениями до SecurityToken и ICryptoProvider, которые поддерживают KeyVault.

Мои проблемы с этим

  1. Я не могу повторно использовать существующий экземпляр KeyVaultClient с этим решением.
  2. Он блокируется (За кадром этозвонки .GetAwaiter().GetResult() на KeyVaultClient.SignAsync
2 голосов
/ 08 июля 2019

Во-первых, токен JWT состоит из трех частей: заголовок, полезная нагрузка и подпись.Все они Base64UrlEncoded.

Вы можете получить подпись следующим образом:

HMAC-SHA256(
 base64urlEncoding(header) + '.' + base64urlEncoding(payload),
 secret
)

Итак, вам нужно сгенерировать заголовок и полезную нагрузку, объединить их по точкам, вычислить хеш итогда вы можете получить подпись.

Вот пример для справки:

var byteData = Encoding.Unicode.GetBytes(base64urlEncoding(header) + "." + base64urlEncoding(payload));
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await keyClient.SignAsync(keyIdentifier, "RS256", digest);
var token = base64urlEncoding(header) + "." + base64urlEncoding(payload) + "." + base64urlEncoding(signature)

Официальная документация SDK для SignAsync

Wiki для JWT

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...